@ebowwa/glm-daemon 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/README.md +264 -0
- package/dist/agent.d.ts +37 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +97 -0
- package/dist/agent.js.map +1 -0
- package/dist/daemon.d.ts +91 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +449 -0
- package/dist/daemon.js.map +1 -0
- package/dist/hooks.d.ts +34 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +82 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/state.d.ts +31 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +67 -0
- package/dist/state.js.map +1 -0
- package/dist/tools.d.ts +42 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +110 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +222 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/worktree.d.ts +42 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +86 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +70 -0
- package/src/agent.js +166 -0
- package/src/agent.ts +110 -0
- package/src/daemon.js +591 -0
- package/src/daemon.ts +529 -0
- package/src/hooks.js +145 -0
- package/src/hooks.ts +94 -0
- package/src/index.js +105 -0
- package/src/index.ts +43 -0
- package/src/state.js +168 -0
- package/src/state.ts +77 -0
- package/src/tools.js +192 -0
- package/src/tools.ts +134 -0
- package/src/types.js +21 -0
- package/src/types.ts +249 -0
- package/src/worktree.js +195 -0
- package/src/worktree.ts +122 -0
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - Hook System
|
|
3
|
+
*
|
|
4
|
+
* Implements hook lifecycle for daemon events.
|
|
5
|
+
* Based on Claude Code's hook system.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { GLMHooksConfig, GLMDaemonState } from "./types.js";
|
|
9
|
+
|
|
10
|
+
type GLMHookHandler = (
|
|
11
|
+
...args: unknown[]
|
|
12
|
+
) => Promise<unknown> | unknown;
|
|
13
|
+
|
|
14
|
+
export class HookSystem {
|
|
15
|
+
private hooks: Map<string, GLMHookHandler[]> = new Map();
|
|
16
|
+
|
|
17
|
+
constructor(config: GLMHooksConfig) {
|
|
18
|
+
// Register hooks from config
|
|
19
|
+
if (config.onSessionStart) {
|
|
20
|
+
this.register("onSessionStart", config.onSessionStart as GLMHookHandler);
|
|
21
|
+
}
|
|
22
|
+
if (config.onSessionEnd) {
|
|
23
|
+
this.register("onSessionEnd", config.onSessionEnd as GLMHookHandler);
|
|
24
|
+
}
|
|
25
|
+
if (config.onPreToolUse) {
|
|
26
|
+
this.register("onPreToolUse", config.onPreToolUse as GLMHookHandler);
|
|
27
|
+
}
|
|
28
|
+
if (config.onPostToolUse) {
|
|
29
|
+
this.register("onPostToolUse", config.onPostToolUse as GLMHookHandler);
|
|
30
|
+
}
|
|
31
|
+
if (config.onSubagentStart) {
|
|
32
|
+
this.register("onSubagentStart", config.onSubagentStart as GLMHookHandler);
|
|
33
|
+
}
|
|
34
|
+
if (config.onSubagentStop) {
|
|
35
|
+
this.register("onSubagentStop", config.onSubagentStop as GLMHookHandler);
|
|
36
|
+
}
|
|
37
|
+
if (config.onIterationStart) {
|
|
38
|
+
this.register("onIterationStart", config.onIterationStart as GLMHookHandler);
|
|
39
|
+
}
|
|
40
|
+
if (config.onIterationEnd) {
|
|
41
|
+
this.register("onIterationEnd", config.onIterationEnd as GLMHookHandler);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Register a hook handler
|
|
47
|
+
*/
|
|
48
|
+
register(event: string, handler: GLMHookHandler): void {
|
|
49
|
+
if (!this.hooks.has(event)) {
|
|
50
|
+
this.hooks.set(event, []);
|
|
51
|
+
}
|
|
52
|
+
this.hooks.get(event)!.push(handler);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Execute all handlers for an event
|
|
57
|
+
*/
|
|
58
|
+
async execute(event: string, ...args: unknown[]): Promise<void> {
|
|
59
|
+
const handlers = this.hooks.get(event);
|
|
60
|
+
if (!handlers) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const handler of handlers) {
|
|
65
|
+
try {
|
|
66
|
+
await handler(...args);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`[HookSystem] Error in ${event}:`, error);
|
|
69
|
+
// Continue executing other hooks even if one fails
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Remove all handlers for an event
|
|
76
|
+
*/
|
|
77
|
+
clear(event: string): void {
|
|
78
|
+
this.hooks.delete(event);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Remove all hooks
|
|
83
|
+
*/
|
|
84
|
+
clearAll(): void {
|
|
85
|
+
this.hooks.clear();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get registered events
|
|
90
|
+
*/
|
|
91
|
+
getEvents(): string[] {
|
|
92
|
+
return Array.from(this.hooks.keys());
|
|
93
|
+
}
|
|
94
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GLM Daemon - Autonomous GLM 4.7 Agent Daemon
|
|
4
|
+
*
|
|
5
|
+
* A daemon for autonomous AI agents powered by GLM 4.7.
|
|
6
|
+
* Implements SLAM pattern (State → Loop → Action → Memory).
|
|
7
|
+
* Supports hooks, tools via MCP, and multi-agent coordination.
|
|
8
|
+
*
|
|
9
|
+
* @module @ebowwa/glm-daemon
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
23
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
36
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
exports.WorktreeManager = exports.StateManager = exports.ToolBridge = exports.HookSystem = exports.GLMAgent = exports.GLMDaemon = void 0;
|
|
63
|
+
exports.createGLMDaemon = createGLMDaemon;
|
|
64
|
+
exports.startGLMDaemon = startGLMDaemon;
|
|
65
|
+
// Main daemon class
|
|
66
|
+
var daemon_js_1 = require("./daemon.js");
|
|
67
|
+
Object.defineProperty(exports, "GLMDaemon", { enumerable: true, get: function () { return daemon_js_1.GLMDaemon; } });
|
|
68
|
+
// Agent class
|
|
69
|
+
var agent_js_1 = require("./agent.js");
|
|
70
|
+
Object.defineProperty(exports, "GLMAgent", { enumerable: true, get: function () { return agent_js_1.GLMAgent; } });
|
|
71
|
+
// Supporting systems
|
|
72
|
+
var hooks_js_1 = require("./hooks.js");
|
|
73
|
+
Object.defineProperty(exports, "HookSystem", { enumerable: true, get: function () { return hooks_js_1.HookSystem; } });
|
|
74
|
+
var tools_js_1 = require("./tools.js");
|
|
75
|
+
Object.defineProperty(exports, "ToolBridge", { enumerable: true, get: function () { return tools_js_1.ToolBridge; } });
|
|
76
|
+
var state_js_1 = require("./state.js");
|
|
77
|
+
Object.defineProperty(exports, "StateManager", { enumerable: true, get: function () { return state_js_1.StateManager; } });
|
|
78
|
+
var worktree_js_1 = require("./worktree.js");
|
|
79
|
+
Object.defineProperty(exports, "WorktreeManager", { enumerable: true, get: function () { return worktree_js_1.WorktreeManager; } });
|
|
80
|
+
// Types
|
|
81
|
+
__exportStar(require("./types.js"), exports);
|
|
82
|
+
// Convenience function to create and start a daemon
|
|
83
|
+
var daemon_js_2 = require("./daemon.js");
|
|
84
|
+
function createGLMDaemon(config) {
|
|
85
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
86
|
+
var daemon;
|
|
87
|
+
return __generator(this, function (_a) {
|
|
88
|
+
daemon = new daemon_js_2.GLMDaemon(config);
|
|
89
|
+
return [2 /*return*/, daemon];
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function startGLMDaemon(config, prompt) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
+
var daemon;
|
|
96
|
+
return __generator(this, function (_a) {
|
|
97
|
+
switch (_a.label) {
|
|
98
|
+
case 0:
|
|
99
|
+
daemon = new daemon_js_2.GLMDaemon(config);
|
|
100
|
+
return [4 /*yield*/, daemon.start(prompt)];
|
|
101
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - Autonomous GLM 4.7 Agent Daemon
|
|
3
|
+
*
|
|
4
|
+
* A daemon for autonomous AI agents powered by GLM 4.7.
|
|
5
|
+
* Implements SLAM pattern (State → Loop → Action → Memory).
|
|
6
|
+
* Supports hooks, tools via MCP, and multi-agent coordination.
|
|
7
|
+
*
|
|
8
|
+
* @module @ebowwa/glm-daemon
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Main daemon class
|
|
12
|
+
export { GLMDaemon } from "./daemon.js";
|
|
13
|
+
|
|
14
|
+
// Agent class
|
|
15
|
+
export { GLMAgent } from "./agent.js";
|
|
16
|
+
|
|
17
|
+
// Supporting systems
|
|
18
|
+
export { HookSystem } from "./hooks.js";
|
|
19
|
+
export { ToolBridge } from "./tools.js";
|
|
20
|
+
export { StateManager } from "./state.js";
|
|
21
|
+
export { WorktreeManager } from "./worktree.js";
|
|
22
|
+
|
|
23
|
+
// Types
|
|
24
|
+
export * from "./types.js";
|
|
25
|
+
|
|
26
|
+
// Convenience function to create and start a daemon
|
|
27
|
+
import { GLMDaemon } from "./daemon.js";
|
|
28
|
+
import type { GLMDaemonConfig } from "./types.js";
|
|
29
|
+
|
|
30
|
+
export async function createGLMDaemon(
|
|
31
|
+
config: GLMDaemonConfig
|
|
32
|
+
): Promise<GLMDaemon> {
|
|
33
|
+
const daemon = new GLMDaemon(config);
|
|
34
|
+
return daemon;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function startGLMDaemon(
|
|
38
|
+
config: GLMDaemonConfig,
|
|
39
|
+
prompt: string
|
|
40
|
+
): Promise<string> {
|
|
41
|
+
const daemon = new GLMDaemon(config);
|
|
42
|
+
return await daemon.start(prompt);
|
|
43
|
+
}
|
package/src/state.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GLM Daemon - State Manager
|
|
4
|
+
*
|
|
5
|
+
* Manages SLAM state persistence to disk.
|
|
6
|
+
*/
|
|
7
|
+
var __assign = (this && this.__assign) || function () {
|
|
8
|
+
__assign = Object.assign || function(t) {
|
|
9
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
10
|
+
s = arguments[i];
|
|
11
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
12
|
+
t[p] = s[p];
|
|
13
|
+
}
|
|
14
|
+
return t;
|
|
15
|
+
};
|
|
16
|
+
return __assign.apply(this, arguments);
|
|
17
|
+
};
|
|
18
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
19
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
20
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
21
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
22
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
23
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
24
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
28
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
29
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
30
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
31
|
+
function step(op) {
|
|
32
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
33
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
34
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
35
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
36
|
+
switch (op[0]) {
|
|
37
|
+
case 0: case 1: t = op; break;
|
|
38
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
39
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
40
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
41
|
+
default:
|
|
42
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
43
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
44
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
45
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
46
|
+
if (t[2]) _.ops.pop();
|
|
47
|
+
_.trys.pop(); continue;
|
|
48
|
+
}
|
|
49
|
+
op = body.call(thisArg, _);
|
|
50
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
51
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.StateManager = void 0;
|
|
56
|
+
var fs_1 = require("fs");
|
|
57
|
+
var StateManager = /** @class */ (function () {
|
|
58
|
+
function StateManager(statePath) {
|
|
59
|
+
this.statePath = statePath;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Load state from disk
|
|
63
|
+
*/
|
|
64
|
+
StateManager.prototype.load = function () {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
66
|
+
var content, _a;
|
|
67
|
+
return __generator(this, function (_b) {
|
|
68
|
+
switch (_b.label) {
|
|
69
|
+
case 0:
|
|
70
|
+
_b.trys.push([0, 2, , 3]);
|
|
71
|
+
return [4 /*yield*/, fs_1.promises.readFile(this.statePath, "utf-8")];
|
|
72
|
+
case 1:
|
|
73
|
+
content = _b.sent();
|
|
74
|
+
return [2 /*return*/, JSON.parse(content)];
|
|
75
|
+
case 2:
|
|
76
|
+
_a = _b.sent();
|
|
77
|
+
// File doesn't exist or invalid JSON
|
|
78
|
+
return [2 /*return*/, null];
|
|
79
|
+
case 3: return [2 /*return*/];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Save state to disk
|
|
86
|
+
*/
|
|
87
|
+
StateManager.prototype.save = function (state) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
+
return __generator(this, function (_a) {
|
|
90
|
+
switch (_a.label) {
|
|
91
|
+
case 0: return [4 /*yield*/, fs_1.promises.writeFile(this.statePath, JSON.stringify(state, null, 2), "utf-8")];
|
|
92
|
+
case 1:
|
|
93
|
+
_a.sent();
|
|
94
|
+
return [2 /*return*/];
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Delete state file
|
|
101
|
+
*/
|
|
102
|
+
StateManager.prototype.delete = function () {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
104
|
+
var _a;
|
|
105
|
+
return __generator(this, function (_b) {
|
|
106
|
+
switch (_b.label) {
|
|
107
|
+
case 0:
|
|
108
|
+
_b.trys.push([0, 2, , 3]);
|
|
109
|
+
return [4 /*yield*/, fs_1.promises.unlink(this.statePath)];
|
|
110
|
+
case 1:
|
|
111
|
+
_b.sent();
|
|
112
|
+
return [3 /*break*/, 3];
|
|
113
|
+
case 2:
|
|
114
|
+
_a = _b.sent();
|
|
115
|
+
return [3 /*break*/, 3];
|
|
116
|
+
case 3: return [2 /*return*/];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Check if state file exists
|
|
123
|
+
*/
|
|
124
|
+
StateManager.prototype.exists = function () {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
126
|
+
var _a;
|
|
127
|
+
return __generator(this, function (_b) {
|
|
128
|
+
switch (_b.label) {
|
|
129
|
+
case 0:
|
|
130
|
+
_b.trys.push([0, 2, , 3]);
|
|
131
|
+
return [4 /*yield*/, fs_1.promises.access(this.statePath)];
|
|
132
|
+
case 1:
|
|
133
|
+
_b.sent();
|
|
134
|
+
return [2 /*return*/, true];
|
|
135
|
+
case 2:
|
|
136
|
+
_a = _b.sent();
|
|
137
|
+
return [2 /*return*/, false];
|
|
138
|
+
case 3: return [2 /*return*/];
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Update a portion of state (merge)
|
|
145
|
+
*/
|
|
146
|
+
StateManager.prototype.update = function (updates) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
148
|
+
var current, updated;
|
|
149
|
+
return __generator(this, function (_a) {
|
|
150
|
+
switch (_a.label) {
|
|
151
|
+
case 0: return [4 /*yield*/, this.load()];
|
|
152
|
+
case 1:
|
|
153
|
+
current = _a.sent();
|
|
154
|
+
if (!current) {
|
|
155
|
+
throw new Error("No existing state to update");
|
|
156
|
+
}
|
|
157
|
+
updated = __assign(__assign({}, current), updates);
|
|
158
|
+
return [4 /*yield*/, this.save(updated)];
|
|
159
|
+
case 2:
|
|
160
|
+
_a.sent();
|
|
161
|
+
return [2 /*return*/, updated];
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
return StateManager;
|
|
167
|
+
}());
|
|
168
|
+
exports.StateManager = StateManager;
|
package/src/state.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - State Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages SLAM state persistence to disk.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { promises as fsp } from "fs";
|
|
8
|
+
import type { GLMDaemonState } from "./types.js";
|
|
9
|
+
|
|
10
|
+
export class StateManager {
|
|
11
|
+
private statePath: string;
|
|
12
|
+
|
|
13
|
+
constructor(statePath: string) {
|
|
14
|
+
this.statePath = statePath;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load state from disk
|
|
19
|
+
*/
|
|
20
|
+
async load(): Promise<GLMDaemonState | null> {
|
|
21
|
+
try {
|
|
22
|
+
const content = await fsp.readFile(this.statePath, "utf-8");
|
|
23
|
+
return JSON.parse(content) as GLMDaemonState;
|
|
24
|
+
} catch {
|
|
25
|
+
// File doesn't exist or invalid JSON
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Save state to disk
|
|
32
|
+
*/
|
|
33
|
+
async save(state: GLMDaemonState): Promise<void> {
|
|
34
|
+
await fsp.writeFile(
|
|
35
|
+
this.statePath,
|
|
36
|
+
JSON.stringify(state, null, 2),
|
|
37
|
+
"utf-8"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Delete state file
|
|
43
|
+
*/
|
|
44
|
+
async delete(): Promise<void> {
|
|
45
|
+
try {
|
|
46
|
+
await fsp.unlink(this.statePath);
|
|
47
|
+
} catch {
|
|
48
|
+
// File doesn't exist, ignore
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check if state file exists
|
|
54
|
+
*/
|
|
55
|
+
async exists(): Promise<boolean> {
|
|
56
|
+
try {
|
|
57
|
+
await fsp.access(this.statePath);
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Update a portion of state (merge)
|
|
66
|
+
*/
|
|
67
|
+
async update(updates: Partial<GLMDaemonState>): Promise<GLMDaemonState> {
|
|
68
|
+
const current = await this.load();
|
|
69
|
+
if (!current) {
|
|
70
|
+
throw new Error("No existing state to update");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const updated = { ...current, ...updates };
|
|
74
|
+
await this.save(updated);
|
|
75
|
+
return updated;
|
|
76
|
+
}
|
|
77
|
+
}
|
package/src/tools.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GLM Daemon - Tool Bridge
|
|
4
|
+
*
|
|
5
|
+
* Connects GLM agents to MCP servers for tool access.
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
17
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
18
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
19
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
20
|
+
function step(op) {
|
|
21
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
22
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
23
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
24
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
25
|
+
switch (op[0]) {
|
|
26
|
+
case 0: case 1: t = op; break;
|
|
27
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
28
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
29
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
30
|
+
default:
|
|
31
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
32
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
33
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
34
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
35
|
+
if (t[2]) _.ops.pop();
|
|
36
|
+
_.trys.pop(); continue;
|
|
37
|
+
}
|
|
38
|
+
op = body.call(thisArg, _);
|
|
39
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
40
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.ToolBridge = void 0;
|
|
45
|
+
var ToolBridge = /** @class */ (function () {
|
|
46
|
+
function ToolBridge(config) {
|
|
47
|
+
if (config === void 0) { config = {}; }
|
|
48
|
+
this.availableTools = [];
|
|
49
|
+
this.config = config;
|
|
50
|
+
this.toolTimeout = config.toolTimeout || 30000;
|
|
51
|
+
this.maxRetries = config.maxRetries || 3;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get list of available tools
|
|
55
|
+
*/
|
|
56
|
+
ToolBridge.prototype.getAvailableTools = function () {
|
|
57
|
+
return this.availableTools;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Set available tools (from MCP discovery)
|
|
61
|
+
*/
|
|
62
|
+
ToolBridge.prototype.setAvailableTools = function (tools) {
|
|
63
|
+
this.availableTools = tools;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Check if a tool is allowed
|
|
67
|
+
*/
|
|
68
|
+
ToolBridge.prototype.isToolAllowed = function (toolName) {
|
|
69
|
+
var _a;
|
|
70
|
+
// Check blacklist first
|
|
71
|
+
if ((_a = this.config.blockedTools) === null || _a === void 0 ? void 0 : _a.includes(toolName)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// If whitelist exists, check it
|
|
75
|
+
if (this.config.allowedTools && this.config.allowedTools.length > 0) {
|
|
76
|
+
return this.config.allowedTools.includes(toolName);
|
|
77
|
+
}
|
|
78
|
+
// Default: allow if not blocked
|
|
79
|
+
return true;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Execute a tool with timeout and retry
|
|
83
|
+
*/
|
|
84
|
+
ToolBridge.prototype.executeTool = function (toolName, args) {
|
|
85
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
86
|
+
var lastError, _loop_1, this_1, attempt, state_1;
|
|
87
|
+
return __generator(this, function (_a) {
|
|
88
|
+
switch (_a.label) {
|
|
89
|
+
case 0:
|
|
90
|
+
if (!this.isToolAllowed(toolName)) {
|
|
91
|
+
return [2 /*return*/, {
|
|
92
|
+
success: false,
|
|
93
|
+
error: "Tool not allowed: ".concat(toolName),
|
|
94
|
+
}];
|
|
95
|
+
}
|
|
96
|
+
lastError = null;
|
|
97
|
+
_loop_1 = function (attempt) {
|
|
98
|
+
var result, error_1;
|
|
99
|
+
return __generator(this, function (_b) {
|
|
100
|
+
switch (_b.label) {
|
|
101
|
+
case 0:
|
|
102
|
+
_b.trys.push([0, 2, , 5]);
|
|
103
|
+
return [4 /*yield*/, this_1.executeWithTimeout(toolName, args)];
|
|
104
|
+
case 1:
|
|
105
|
+
result = _b.sent();
|
|
106
|
+
return [2 /*return*/, { value: { success: true, result: result } }];
|
|
107
|
+
case 2:
|
|
108
|
+
error_1 = _b.sent();
|
|
109
|
+
lastError = error_1;
|
|
110
|
+
if (!(attempt < this_1.maxRetries - 1)) return [3 /*break*/, 4];
|
|
111
|
+
return [4 /*yield*/, new Promise(function (resolve) {
|
|
112
|
+
return setTimeout(resolve, Math.pow(2, attempt) * 1000);
|
|
113
|
+
})];
|
|
114
|
+
case 3:
|
|
115
|
+
_b.sent();
|
|
116
|
+
_b.label = 4;
|
|
117
|
+
case 4: return [3 /*break*/, 5];
|
|
118
|
+
case 5: return [2 /*return*/];
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
this_1 = this;
|
|
123
|
+
attempt = 0;
|
|
124
|
+
_a.label = 1;
|
|
125
|
+
case 1:
|
|
126
|
+
if (!(attempt < this.maxRetries)) return [3 /*break*/, 4];
|
|
127
|
+
return [5 /*yield**/, _loop_1(attempt)];
|
|
128
|
+
case 2:
|
|
129
|
+
state_1 = _a.sent();
|
|
130
|
+
if (typeof state_1 === "object")
|
|
131
|
+
return [2 /*return*/, state_1.value];
|
|
132
|
+
_a.label = 3;
|
|
133
|
+
case 3:
|
|
134
|
+
attempt++;
|
|
135
|
+
return [3 /*break*/, 1];
|
|
136
|
+
case 4: return [2 /*return*/, {
|
|
137
|
+
success: false,
|
|
138
|
+
error: (lastError === null || lastError === void 0 ? void 0 : lastError.message) || "Unknown error",
|
|
139
|
+
}];
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Execute tool with timeout
|
|
146
|
+
*/
|
|
147
|
+
ToolBridge.prototype.executeWithTimeout = function (toolName, args) {
|
|
148
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
149
|
+
var _this = this;
|
|
150
|
+
return __generator(this, function (_a) {
|
|
151
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
152
|
+
var timer = setTimeout(function () {
|
|
153
|
+
reject(new Error("Tool timeout: ".concat(toolName)));
|
|
154
|
+
}, _this.toolTimeout);
|
|
155
|
+
// TODO: Actually call MCP tool here
|
|
156
|
+
// For now, this is a placeholder
|
|
157
|
+
setTimeout(function () {
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
resolve("Executed ".concat(toolName, " with ").concat(JSON.stringify(args)));
|
|
160
|
+
}, 100);
|
|
161
|
+
})];
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Discover tools from MCP servers
|
|
167
|
+
*/
|
|
168
|
+
ToolBridge.prototype.discoverMCPTools = function () {
|
|
169
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
170
|
+
var commonTools;
|
|
171
|
+
return __generator(this, function (_a) {
|
|
172
|
+
if (!this.config.enableMCP) {
|
|
173
|
+
return [2 /*return*/];
|
|
174
|
+
}
|
|
175
|
+
commonTools = [
|
|
176
|
+
"Read",
|
|
177
|
+
"Write",
|
|
178
|
+
"Edit",
|
|
179
|
+
"Grep",
|
|
180
|
+
"Glob",
|
|
181
|
+
"Bash",
|
|
182
|
+
"git_status",
|
|
183
|
+
"git_commit",
|
|
184
|
+
];
|
|
185
|
+
this.setAvailableTools(commonTools);
|
|
186
|
+
return [2 /*return*/];
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
return ToolBridge;
|
|
191
|
+
}());
|
|
192
|
+
exports.ToolBridge = ToolBridge;
|