opc-agent 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -24
- package/dist/channels/dingtalk.d.ts +17 -0
- package/dist/channels/dingtalk.js +38 -0
- package/dist/channels/googlechat.d.ts +14 -0
- package/dist/channels/googlechat.js +37 -0
- package/dist/channels/imessage.d.ts +13 -0
- package/dist/channels/imessage.js +28 -0
- package/dist/channels/irc.d.ts +20 -0
- package/dist/channels/irc.js +71 -0
- package/dist/channels/line.d.ts +14 -0
- package/dist/channels/line.js +28 -0
- package/dist/channels/matrix.d.ts +15 -0
- package/dist/channels/matrix.js +28 -0
- package/dist/channels/mattermost.d.ts +18 -0
- package/dist/channels/mattermost.js +49 -0
- package/dist/channels/msteams.d.ts +14 -0
- package/dist/channels/msteams.js +28 -0
- package/dist/channels/nostr.d.ts +14 -0
- package/dist/channels/nostr.js +28 -0
- package/dist/channels/qq.d.ts +15 -0
- package/dist/channels/qq.js +28 -0
- package/dist/channels/signal.d.ts +14 -0
- package/dist/channels/signal.js +28 -0
- package/dist/channels/sms.d.ts +15 -0
- package/dist/channels/sms.js +28 -0
- package/dist/channels/twitch.d.ts +17 -0
- package/dist/channels/twitch.js +59 -0
- package/dist/channels/voice-call.d.ts +27 -0
- package/dist/channels/voice-call.js +82 -0
- package/dist/channels/whatsapp.d.ts +14 -0
- package/dist/channels/whatsapp.js +28 -0
- package/dist/cli.js +36 -0
- package/dist/core/api-server.d.ts +25 -0
- package/dist/core/api-server.js +286 -0
- package/dist/core/audio.d.ts +50 -0
- package/dist/core/audio.js +68 -0
- package/dist/core/context-discovery.d.ts +16 -0
- package/dist/core/context-discovery.js +107 -0
- package/dist/core/context-refs.d.ts +29 -0
- package/dist/core/context-refs.js +162 -0
- package/dist/core/gateway.d.ts +53 -0
- package/dist/core/gateway.js +80 -0
- package/dist/core/heartbeat.d.ts +19 -0
- package/dist/core/heartbeat.js +50 -0
- package/dist/core/hooks.d.ts +28 -0
- package/dist/core/hooks.js +82 -0
- package/dist/core/ide-bridge.d.ts +53 -0
- package/dist/core/ide-bridge.js +97 -0
- package/dist/core/node-network.d.ts +23 -0
- package/dist/core/node-network.js +77 -0
- package/dist/core/profiles.d.ts +27 -0
- package/dist/core/profiles.js +131 -0
- package/dist/core/sandbox.d.ts +25 -0
- package/dist/core/sandbox.js +84 -1
- package/dist/core/session-manager.d.ts +33 -0
- package/dist/core/session-manager.js +157 -0
- package/dist/core/vision.d.ts +45 -0
- package/dist/core/vision.js +177 -0
- package/dist/index.d.ts +64 -1
- package/dist/index.js +86 -3
- package/dist/memory/context-compressor.d.ts +43 -0
- package/dist/memory/context-compressor.js +167 -0
- package/dist/memory/index.d.ts +4 -0
- package/dist/memory/index.js +5 -1
- package/dist/memory/user-profiler.d.ts +50 -0
- package/dist/memory/user-profiler.js +201 -0
- package/dist/schema/oad.d.ts +12 -12
- package/dist/security/approvals.d.ts +53 -0
- package/dist/security/approvals.js +115 -0
- package/dist/security/elevated.d.ts +41 -0
- package/dist/security/elevated.js +89 -0
- package/dist/security/index.d.ts +6 -0
- package/dist/security/index.js +7 -1
- package/dist/security/secrets.d.ts +34 -0
- package/dist/security/secrets.js +115 -0
- package/dist/tools/builtin/browser.d.ts +47 -0
- package/dist/tools/builtin/browser.js +284 -0
- package/dist/tools/builtin/home-assistant.d.ts +12 -0
- package/dist/tools/builtin/home-assistant.js +126 -0
- package/dist/tools/builtin/index.d.ts +6 -1
- package/dist/tools/builtin/index.js +18 -2
- package/dist/tools/builtin/rl-tools.d.ts +13 -0
- package/dist/tools/builtin/rl-tools.js +228 -0
- package/dist/tools/builtin/vision.d.ts +6 -0
- package/dist/tools/builtin/vision.js +61 -0
- package/package.json +2 -2
- package/src/channels/dingtalk.ts +46 -0
- package/src/channels/googlechat.ts +42 -0
- package/src/channels/imessage.ts +32 -0
- package/src/channels/irc.ts +82 -0
- package/src/channels/line.ts +33 -0
- package/src/channels/matrix.ts +34 -0
- package/src/channels/mattermost.ts +57 -0
- package/src/channels/msteams.ts +33 -0
- package/src/channels/nostr.ts +33 -0
- package/src/channels/qq.ts +34 -0
- package/src/channels/signal.ts +33 -0
- package/src/channels/sms.ts +34 -0
- package/src/channels/twitch.ts +65 -0
- package/src/channels/voice-call.ts +100 -0
- package/src/channels/whatsapp.ts +33 -0
- package/src/cli.ts +40 -0
- package/src/core/api-server.ts +277 -0
- package/src/core/audio.ts +98 -0
- package/src/core/context-discovery.ts +85 -0
- package/src/core/context-refs.ts +140 -0
- package/src/core/gateway.ts +106 -0
- package/src/core/heartbeat.ts +51 -0
- package/src/core/hooks.ts +105 -0
- package/src/core/ide-bridge.ts +133 -0
- package/src/core/node-network.ts +86 -0
- package/src/core/profiles.ts +122 -0
- package/src/core/sandbox.ts +100 -0
- package/src/core/session-manager.ts +137 -0
- package/src/core/vision.ts +180 -0
- package/src/index.ts +84 -1
- package/src/memory/context-compressor.ts +189 -0
- package/src/memory/index.ts +4 -0
- package/src/memory/user-profiler.ts +215 -0
- package/src/security/approvals.ts +143 -0
- package/src/security/elevated.ts +105 -0
- package/src/security/index.ts +6 -0
- package/src/security/secrets.ts +129 -0
- package/src/tools/builtin/browser.ts +299 -0
- package/src/tools/builtin/home-assistant.ts +116 -0
- package/src/tools/builtin/index.ts +9 -2
- package/src/tools/builtin/rl-tools.ts +243 -0
- package/src/tools/builtin/vision.ts +64 -0
- package/tests/api-server.test.ts +148 -0
- package/tests/approvals.test.ts +89 -0
- package/tests/audio.test.ts +40 -0
- package/tests/browser.test.ts +179 -0
- package/tests/builtin-tools.test.ts +83 -83
- package/tests/channels-extra.test.ts +45 -0
- package/tests/context-compressor.test.ts +172 -0
- package/tests/context-refs.test.ts +121 -0
- package/tests/elevated.test.ts +69 -0
- package/tests/gateway.test.ts +63 -71
- package/tests/home-assistant.test.ts +40 -0
- package/tests/hooks.test.ts +79 -0
- package/tests/ide-bridge.test.ts +38 -0
- package/tests/node-network.test.ts +74 -0
- package/tests/profiles.test.ts +61 -0
- package/tests/rl-tools.test.ts +93 -0
- package/tests/sandbox-manager.test.ts +46 -0
- package/tests/secrets.test.ts +107 -0
- package/tests/tools/builtin-extended.test.ts +138 -138
- package/tests/user-profiler.test.ts +169 -0
- package/tests/v090-features.test.ts +254 -0
- package/tests/vision.test.ts +61 -0
- package/tests/voice-call.test.ts +47 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hooks Module - v1.0.0
|
|
4
|
+
* Event hook system with priority ordering and context modification.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.HookManager = exports.ALL_HOOK_EVENTS = void 0;
|
|
8
|
+
exports.ALL_HOOK_EVENTS = [
|
|
9
|
+
'before:message', 'after:message',
|
|
10
|
+
'before:tool', 'after:tool',
|
|
11
|
+
'before:llm', 'after:llm',
|
|
12
|
+
'before:send', 'after:send',
|
|
13
|
+
'before:learn', 'after:learn',
|
|
14
|
+
'before:recall', 'after:recall',
|
|
15
|
+
'on:error', 'on:start', 'on:stop',
|
|
16
|
+
];
|
|
17
|
+
let hookIdCounter = 0;
|
|
18
|
+
class HookManager {
|
|
19
|
+
hooks = new Map();
|
|
20
|
+
register(event, handler, options) {
|
|
21
|
+
const id = `hook_${++hookIdCounter}`;
|
|
22
|
+
const entry = {
|
|
23
|
+
id,
|
|
24
|
+
event,
|
|
25
|
+
handler,
|
|
26
|
+
priority: options?.priority ?? 100,
|
|
27
|
+
name: options?.name,
|
|
28
|
+
};
|
|
29
|
+
if (!this.hooks.has(event))
|
|
30
|
+
this.hooks.set(event, []);
|
|
31
|
+
const list = this.hooks.get(event);
|
|
32
|
+
list.push(entry);
|
|
33
|
+
list.sort((a, b) => a.priority - b.priority);
|
|
34
|
+
return id;
|
|
35
|
+
}
|
|
36
|
+
unregister(id) {
|
|
37
|
+
for (const [event, list] of this.hooks) {
|
|
38
|
+
const idx = list.findIndex(h => h.id === id);
|
|
39
|
+
if (idx !== -1) {
|
|
40
|
+
list.splice(idx, 1);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
async run(event, ctx = {}) {
|
|
47
|
+
const list = this.hooks.get(event);
|
|
48
|
+
if (!list || list.length === 0)
|
|
49
|
+
return ctx;
|
|
50
|
+
let current = { ...ctx };
|
|
51
|
+
for (const hook of list) {
|
|
52
|
+
const result = await hook.handler(current);
|
|
53
|
+
if (result)
|
|
54
|
+
current = { ...current, ...result };
|
|
55
|
+
}
|
|
56
|
+
return current;
|
|
57
|
+
}
|
|
58
|
+
getRegistered(event) {
|
|
59
|
+
const results = [];
|
|
60
|
+
const events = event ? [event] : exports.ALL_HOOK_EVENTS;
|
|
61
|
+
for (const e of events) {
|
|
62
|
+
const list = this.hooks.get(e) ?? [];
|
|
63
|
+
for (const h of list) {
|
|
64
|
+
results.push({ id: h.id, event: h.event, priority: h.priority, name: h.name });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
clear(event) {
|
|
70
|
+
if (event) {
|
|
71
|
+
this.hooks.delete(event);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.hooks.clear();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
hasHooks(event) {
|
|
78
|
+
return (this.hooks.get(event)?.length ?? 0) > 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.HookManager = HookManager;
|
|
82
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface IDEConfig {
|
|
2
|
+
editor: 'vscode' | 'jetbrains' | 'zed' | 'cursor';
|
|
3
|
+
workspacePath?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Diagnostic {
|
|
6
|
+
path: string;
|
|
7
|
+
line: number;
|
|
8
|
+
column: number;
|
|
9
|
+
severity: 'error' | 'warning' | 'info';
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
export interface TextEdit {
|
|
13
|
+
range: Range;
|
|
14
|
+
newText: string;
|
|
15
|
+
}
|
|
16
|
+
export interface Range {
|
|
17
|
+
startLine: number;
|
|
18
|
+
startColumn: number;
|
|
19
|
+
endLine: number;
|
|
20
|
+
endColumn: number;
|
|
21
|
+
}
|
|
22
|
+
export interface SearchOptions {
|
|
23
|
+
caseSensitive?: boolean;
|
|
24
|
+
regex?: boolean;
|
|
25
|
+
include?: string;
|
|
26
|
+
exclude?: string;
|
|
27
|
+
maxResults?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface SearchResult {
|
|
30
|
+
path: string;
|
|
31
|
+
line: number;
|
|
32
|
+
column: number;
|
|
33
|
+
text: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class IDEBridge {
|
|
36
|
+
private config;
|
|
37
|
+
constructor(config: IDEConfig);
|
|
38
|
+
private getCliCommand;
|
|
39
|
+
private exec;
|
|
40
|
+
openFile(path: string, line?: number): Promise<void>;
|
|
41
|
+
getDiagnostics(path?: string): Promise<Diagnostic[]>;
|
|
42
|
+
runCommand(command: string): Promise<string>;
|
|
43
|
+
getOpenFiles(): Promise<string[]>;
|
|
44
|
+
applyEdit(path: string, edits: TextEdit[]): Promise<void>;
|
|
45
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
46
|
+
getSelection(): Promise<{
|
|
47
|
+
path: string;
|
|
48
|
+
text: string;
|
|
49
|
+
range: Range;
|
|
50
|
+
} | null>;
|
|
51
|
+
installExtension(extensionId: string): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=ide-bridge.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IDEBridge = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
class IDEBridge {
|
|
6
|
+
config;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
getCliCommand() {
|
|
11
|
+
switch (this.config.editor) {
|
|
12
|
+
case 'vscode':
|
|
13
|
+
case 'cursor': return this.config.editor === 'cursor' ? 'cursor' : 'code';
|
|
14
|
+
case 'jetbrains': return 'idea';
|
|
15
|
+
case 'zed': return 'zed';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exec(cmd) {
|
|
19
|
+
try {
|
|
20
|
+
return (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', timeout: 10000, cwd: this.config.workspacePath }).trim();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
throw new Error(`IDE command failed: ${e.message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async openFile(path, line) {
|
|
27
|
+
const cli = this.getCliCommand();
|
|
28
|
+
const target = line ? `${path}:${line}` : path;
|
|
29
|
+
if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
|
|
30
|
+
this.exec(`${cli} --goto "${target}"`);
|
|
31
|
+
}
|
|
32
|
+
else if (this.config.editor === 'zed') {
|
|
33
|
+
this.exec(`zed "${target}"`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.exec(`${cli} --line ${line || 1} "${path}"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async getDiagnostics(path) {
|
|
40
|
+
// VS Code doesn't expose diagnostics via CLI; return empty as stub
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
async runCommand(command) {
|
|
44
|
+
const cli = this.getCliCommand();
|
|
45
|
+
if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
|
|
46
|
+
return this.exec(`${cli} --command "${command}"`);
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`runCommand not supported for ${this.config.editor}`);
|
|
49
|
+
}
|
|
50
|
+
async getOpenFiles() {
|
|
51
|
+
// Stub — no standard CLI to get open files
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
async applyEdit(path, edits) {
|
|
55
|
+
// Stub — would use editor's API/extension
|
|
56
|
+
if (edits.length === 0)
|
|
57
|
+
return;
|
|
58
|
+
throw new Error('applyEdit requires an IDE extension to be installed. Use file system edits as fallback.');
|
|
59
|
+
}
|
|
60
|
+
async search(query, options) {
|
|
61
|
+
const cli = this.getCliCommand();
|
|
62
|
+
if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
|
|
63
|
+
try {
|
|
64
|
+
const args = [`--search "${query}"`];
|
|
65
|
+
if (options?.include)
|
|
66
|
+
args.push(`--include "${options.include}"`);
|
|
67
|
+
const output = this.exec(`${cli} ${args.join(' ')}`);
|
|
68
|
+
// Parse output lines
|
|
69
|
+
return output.split('\n').filter(Boolean).map(line => {
|
|
70
|
+
const match = line.match(/^(.+):(\d+):(\d+):(.*)$/);
|
|
71
|
+
if (!match)
|
|
72
|
+
return { path: '', line: 0, column: 0, text: line };
|
|
73
|
+
return { path: match[1], line: parseInt(match[2]), column: parseInt(match[3]), text: match[4] };
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
async getSelection() {
|
|
83
|
+
// Stub — requires editor extension
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
async installExtension(extensionId) {
|
|
87
|
+
const cli = this.getCliCommand();
|
|
88
|
+
if (this.config.editor === 'vscode' || this.config.editor === 'cursor') {
|
|
89
|
+
this.exec(`${cli} --install-extension ${extensionId}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
throw new Error(`installExtension not supported for ${this.config.editor}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.IDEBridge = IDEBridge;
|
|
97
|
+
//# sourceMappingURL=ide-bridge.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface RemoteNode {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
type: 'vps' | 'pi' | 'phone' | 'desktop';
|
|
8
|
+
status: 'online' | 'offline' | 'pairing';
|
|
9
|
+
capabilities: string[];
|
|
10
|
+
lastSeen: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class NodeNetwork extends EventEmitter {
|
|
13
|
+
private nodes;
|
|
14
|
+
addNode(config: Partial<RemoteNode>): RemoteNode;
|
|
15
|
+
removeNode(id: string): void;
|
|
16
|
+
listNodes(): RemoteNode[];
|
|
17
|
+
getNode(id: string): RemoteNode | null;
|
|
18
|
+
pair(nodeId: string, pairingCode: string): Promise<boolean>;
|
|
19
|
+
sendCommand(nodeId: string, command: string): Promise<any>;
|
|
20
|
+
broadcast(command: string): Promise<Map<string, any>>;
|
|
21
|
+
healthCheck(): Promise<Map<string, boolean>>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=node-network.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NodeNetwork = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
class NodeNetwork extends events_1.EventEmitter {
|
|
7
|
+
nodes = new Map();
|
|
8
|
+
addNode(config) {
|
|
9
|
+
const node = {
|
|
10
|
+
id: config.id || (0, crypto_1.randomUUID)(),
|
|
11
|
+
name: config.name || 'unnamed',
|
|
12
|
+
host: config.host || 'localhost',
|
|
13
|
+
port: config.port || 8080,
|
|
14
|
+
type: config.type || 'desktop',
|
|
15
|
+
status: config.status || 'offline',
|
|
16
|
+
capabilities: config.capabilities || [],
|
|
17
|
+
lastSeen: Date.now(),
|
|
18
|
+
};
|
|
19
|
+
this.nodes.set(node.id, node);
|
|
20
|
+
return node;
|
|
21
|
+
}
|
|
22
|
+
removeNode(id) {
|
|
23
|
+
if (!this.nodes.has(id))
|
|
24
|
+
throw new Error(`Node ${id} not found`);
|
|
25
|
+
this.nodes.delete(id);
|
|
26
|
+
}
|
|
27
|
+
listNodes() {
|
|
28
|
+
return Array.from(this.nodes.values());
|
|
29
|
+
}
|
|
30
|
+
getNode(id) {
|
|
31
|
+
return this.nodes.get(id) || null;
|
|
32
|
+
}
|
|
33
|
+
async pair(nodeId, pairingCode) {
|
|
34
|
+
const node = this.nodes.get(nodeId);
|
|
35
|
+
if (!node)
|
|
36
|
+
throw new Error(`Node ${nodeId} not found`);
|
|
37
|
+
if (!pairingCode || pairingCode.length < 4)
|
|
38
|
+
return false;
|
|
39
|
+
node.status = 'online';
|
|
40
|
+
node.lastSeen = Date.now();
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
async sendCommand(nodeId, command) {
|
|
44
|
+
const node = this.nodes.get(nodeId);
|
|
45
|
+
if (!node)
|
|
46
|
+
throw new Error(`Node ${nodeId} not found`);
|
|
47
|
+
if (node.status !== 'online')
|
|
48
|
+
throw new Error(`Node ${nodeId} is ${node.status}`);
|
|
49
|
+
node.lastSeen = Date.now();
|
|
50
|
+
// Stub: return command echo
|
|
51
|
+
return { nodeId, command, status: 'sent', timestamp: Date.now() };
|
|
52
|
+
}
|
|
53
|
+
async broadcast(command) {
|
|
54
|
+
const results = new Map();
|
|
55
|
+
for (const [id, node] of this.nodes) {
|
|
56
|
+
if (node.status === 'online') {
|
|
57
|
+
try {
|
|
58
|
+
results.set(id, await this.sendCommand(id, command));
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
results.set(id, { error: e.message });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
async healthCheck() {
|
|
68
|
+
const results = new Map();
|
|
69
|
+
for (const [id, node] of this.nodes) {
|
|
70
|
+
results.set(id, node.status === 'online');
|
|
71
|
+
node.lastSeen = Date.now();
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.NodeNetwork = NodeNetwork;
|
|
77
|
+
//# sourceMappingURL=node-network.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ProfileConfig {
|
|
2
|
+
model?: string;
|
|
3
|
+
systemPrompt?: string;
|
|
4
|
+
temperature?: number;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export interface Profile {
|
|
8
|
+
name: string;
|
|
9
|
+
config: ProfileConfig;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
lastUsed: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class ProfileManager {
|
|
14
|
+
private profilesDir;
|
|
15
|
+
private currentName;
|
|
16
|
+
constructor(baseDir?: string);
|
|
17
|
+
private ensureDir;
|
|
18
|
+
private profileDir;
|
|
19
|
+
private profileFile;
|
|
20
|
+
create(name: string, config?: ProfileConfig): Profile;
|
|
21
|
+
switch(name: string): void;
|
|
22
|
+
list(): Profile[];
|
|
23
|
+
get(name: string): Profile;
|
|
24
|
+
delete(name: string): void;
|
|
25
|
+
current(): Profile;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ProfileManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
// ─── ProfileManager ─────────────────────────────────────────
|
|
41
|
+
class ProfileManager {
|
|
42
|
+
profilesDir;
|
|
43
|
+
currentName = 'default';
|
|
44
|
+
constructor(baseDir) {
|
|
45
|
+
this.profilesDir = baseDir ?? path.join(os.homedir(), '.opc', 'profiles');
|
|
46
|
+
this.ensureDir(this.profilesDir);
|
|
47
|
+
// Load current profile pointer
|
|
48
|
+
const pointerFile = path.join(this.profilesDir, '.current');
|
|
49
|
+
if (fs.existsSync(pointerFile)) {
|
|
50
|
+
this.currentName = fs.readFileSync(pointerFile, 'utf-8').trim();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
ensureDir(dir) {
|
|
54
|
+
if (!fs.existsSync(dir)) {
|
|
55
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
profileDir(name) {
|
|
59
|
+
return path.join(this.profilesDir, name);
|
|
60
|
+
}
|
|
61
|
+
profileFile(name) {
|
|
62
|
+
return path.join(this.profileDir(name), 'profile.json');
|
|
63
|
+
}
|
|
64
|
+
create(name, config = {}) {
|
|
65
|
+
const dir = this.profileDir(name);
|
|
66
|
+
if (fs.existsSync(dir)) {
|
|
67
|
+
throw new Error(`Profile '${name}' already exists`);
|
|
68
|
+
}
|
|
69
|
+
this.ensureDir(dir);
|
|
70
|
+
// Also create memory and sessions dirs
|
|
71
|
+
this.ensureDir(path.join(dir, 'memory'));
|
|
72
|
+
this.ensureDir(path.join(dir, 'sessions'));
|
|
73
|
+
const profile = {
|
|
74
|
+
name,
|
|
75
|
+
config,
|
|
76
|
+
createdAt: Date.now(),
|
|
77
|
+
lastUsed: Date.now(),
|
|
78
|
+
};
|
|
79
|
+
fs.writeFileSync(this.profileFile(name), JSON.stringify(profile, null, 2));
|
|
80
|
+
return profile;
|
|
81
|
+
}
|
|
82
|
+
switch(name) {
|
|
83
|
+
if (!fs.existsSync(this.profileDir(name))) {
|
|
84
|
+
throw new Error(`Profile '${name}' does not exist`);
|
|
85
|
+
}
|
|
86
|
+
this.currentName = name;
|
|
87
|
+
fs.writeFileSync(path.join(this.profilesDir, '.current'), name);
|
|
88
|
+
// Update lastUsed
|
|
89
|
+
const profile = this.get(name);
|
|
90
|
+
profile.lastUsed = Date.now();
|
|
91
|
+
fs.writeFileSync(this.profileFile(name), JSON.stringify(profile, null, 2));
|
|
92
|
+
}
|
|
93
|
+
list() {
|
|
94
|
+
if (!fs.existsSync(this.profilesDir))
|
|
95
|
+
return [];
|
|
96
|
+
return fs.readdirSync(this.profilesDir)
|
|
97
|
+
.filter(f => {
|
|
98
|
+
const full = path.join(this.profilesDir, f);
|
|
99
|
+
return fs.statSync(full).isDirectory() && fs.existsSync(path.join(full, 'profile.json'));
|
|
100
|
+
})
|
|
101
|
+
.map(f => this.get(f));
|
|
102
|
+
}
|
|
103
|
+
get(name) {
|
|
104
|
+
const file = this.profileFile(name);
|
|
105
|
+
if (!fs.existsSync(file)) {
|
|
106
|
+
throw new Error(`Profile '${name}' not found`);
|
|
107
|
+
}
|
|
108
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
109
|
+
}
|
|
110
|
+
delete(name) {
|
|
111
|
+
if (name === this.currentName) {
|
|
112
|
+
throw new Error(`Cannot delete the current active profile '${name}'`);
|
|
113
|
+
}
|
|
114
|
+
const dir = this.profileDir(name);
|
|
115
|
+
if (!fs.existsSync(dir)) {
|
|
116
|
+
throw new Error(`Profile '${name}' does not exist`);
|
|
117
|
+
}
|
|
118
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
current() {
|
|
121
|
+
try {
|
|
122
|
+
return this.get(this.currentName);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Auto-create default
|
|
126
|
+
return this.create(this.currentName);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.ProfileManager = ProfileManager;
|
|
131
|
+
//# sourceMappingURL=profiles.js.map
|
package/dist/core/sandbox.d.ts
CHANGED
|
@@ -51,4 +51,29 @@ export declare class Sandbox {
|
|
|
51
51
|
getMaxFileSize(): number;
|
|
52
52
|
getMaxFiles(): number;
|
|
53
53
|
}
|
|
54
|
+
export interface RemoteSandboxConfig {
|
|
55
|
+
backend: 'local' | 'docker' | 'ssh';
|
|
56
|
+
docker?: {
|
|
57
|
+
image: string;
|
|
58
|
+
volumes?: string[];
|
|
59
|
+
};
|
|
60
|
+
ssh?: {
|
|
61
|
+
host: string;
|
|
62
|
+
user: string;
|
|
63
|
+
keyPath?: string;
|
|
64
|
+
};
|
|
65
|
+
timeout?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface ExecResult {
|
|
68
|
+
stdout: string;
|
|
69
|
+
stderr: string;
|
|
70
|
+
exitCode: number;
|
|
71
|
+
}
|
|
72
|
+
export declare class SandboxManager {
|
|
73
|
+
private defaultConfig;
|
|
74
|
+
constructor(config?: Partial<RemoteSandboxConfig>);
|
|
75
|
+
exec(command: string, config?: Partial<RemoteSandboxConfig>): Promise<ExecResult>;
|
|
76
|
+
upload(localPath: string, remotePath: string, config?: Partial<RemoteSandboxConfig>): Promise<void>;
|
|
77
|
+
download(remotePath: string, localPath: string, config?: Partial<RemoteSandboxConfig>): Promise<void>;
|
|
78
|
+
}
|
|
54
79
|
//# sourceMappingURL=sandbox.d.ts.map
|
package/dist/core/sandbox.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Sandbox = void 0;
|
|
36
|
+
exports.SandboxManager = exports.Sandbox = void 0;
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
const TRUST_RESTRICTIONS = {
|
|
@@ -232,4 +232,87 @@ class Sandbox {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
exports.Sandbox = Sandbox;
|
|
235
|
+
class SandboxManager {
|
|
236
|
+
defaultConfig;
|
|
237
|
+
constructor(config) {
|
|
238
|
+
this.defaultConfig = {
|
|
239
|
+
backend: config?.backend ?? 'local',
|
|
240
|
+
docker: config?.docker,
|
|
241
|
+
ssh: config?.ssh,
|
|
242
|
+
timeout: config?.timeout ?? 30000,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async exec(command, config) {
|
|
246
|
+
const cfg = { ...this.defaultConfig, ...config };
|
|
247
|
+
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
248
|
+
switch (cfg.backend) {
|
|
249
|
+
case 'local': {
|
|
250
|
+
try {
|
|
251
|
+
const stdout = execSync(command, {
|
|
252
|
+
timeout: cfg.timeout,
|
|
253
|
+
encoding: 'utf-8',
|
|
254
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
255
|
+
});
|
|
256
|
+
return { stdout: stdout ?? '', stderr: '', exitCode: 0 };
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
return {
|
|
260
|
+
stdout: err.stdout ?? '',
|
|
261
|
+
stderr: err.stderr ?? '',
|
|
262
|
+
exitCode: err.status ?? 1,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
case 'docker': {
|
|
267
|
+
if (!cfg.docker?.image)
|
|
268
|
+
throw new Error('Docker image is required');
|
|
269
|
+
const volumes = (cfg.docker.volumes ?? []).map(v => `-v ${v}`).join(' ');
|
|
270
|
+
const dockerCmd = `docker run --rm ${volumes} ${cfg.docker.image} sh -c "${command.replace(/"/g, '\\"')}"`;
|
|
271
|
+
return this.exec(dockerCmd, { backend: 'local', timeout: cfg.timeout });
|
|
272
|
+
}
|
|
273
|
+
case 'ssh': {
|
|
274
|
+
if (!cfg.ssh?.host || !cfg.ssh?.user)
|
|
275
|
+
throw new Error('SSH host and user are required');
|
|
276
|
+
const keyArg = cfg.ssh.keyPath ? `-i ${cfg.ssh.keyPath}` : '';
|
|
277
|
+
const sshCmd = `ssh ${keyArg} ${cfg.ssh.user}@${cfg.ssh.host} "${command.replace(/"/g, '\\"')}"`;
|
|
278
|
+
return this.exec(sshCmd, { backend: 'local', timeout: cfg.timeout });
|
|
279
|
+
}
|
|
280
|
+
default:
|
|
281
|
+
throw new Error(`Unknown sandbox backend: ${cfg.backend}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async upload(localPath, remotePath, config) {
|
|
285
|
+
const cfg = { ...this.defaultConfig, ...config };
|
|
286
|
+
if (cfg.backend === 'local') {
|
|
287
|
+
const fsp = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
288
|
+
fsp.copyFileSync(localPath, remotePath);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (cfg.backend === 'ssh') {
|
|
292
|
+
const keyArg = cfg.ssh?.keyPath ? `-i ${cfg.ssh.keyPath}` : '';
|
|
293
|
+
await this.exec(`scp ${keyArg} "${localPath}" ${cfg.ssh.user}@${cfg.ssh.host}:"${remotePath}"`, { backend: 'local' });
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (cfg.backend === 'docker') {
|
|
297
|
+
throw new Error('Upload to docker not yet supported. Use volumes instead.');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async download(remotePath, localPath, config) {
|
|
301
|
+
const cfg = { ...this.defaultConfig, ...config };
|
|
302
|
+
if (cfg.backend === 'local') {
|
|
303
|
+
const fsp = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
304
|
+
fsp.copyFileSync(remotePath, localPath);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (cfg.backend === 'ssh') {
|
|
308
|
+
const keyArg = cfg.ssh?.keyPath ? `-i ${cfg.ssh.keyPath}` : '';
|
|
309
|
+
await this.exec(`scp ${keyArg} ${cfg.ssh.user}@${cfg.ssh.host}:"${remotePath}" "${localPath}"`, { backend: 'local' });
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (cfg.backend === 'docker') {
|
|
313
|
+
throw new Error('Download from docker not yet supported. Use volumes instead.');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
exports.SandboxManager = SandboxManager;
|
|
235
318
|
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Message } from './types';
|
|
2
|
+
export interface Session {
|
|
3
|
+
id: string;
|
|
4
|
+
agentId: string;
|
|
5
|
+
channel: string;
|
|
6
|
+
messages: Message[];
|
|
7
|
+
metadata: Record<string, any>;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
lastActivity: number;
|
|
10
|
+
parentId?: string;
|
|
11
|
+
compactedAt?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class SessionManager {
|
|
14
|
+
private sessions;
|
|
15
|
+
private storageDir;
|
|
16
|
+
constructor(storageDir?: string);
|
|
17
|
+
create(agentId: string, channel: string, parentId?: string): Session;
|
|
18
|
+
get(id: string): Session | null;
|
|
19
|
+
list(filter?: {
|
|
20
|
+
agentId?: string;
|
|
21
|
+
channel?: string;
|
|
22
|
+
active?: boolean;
|
|
23
|
+
}): Session[];
|
|
24
|
+
addMessage(sessionId: string, message: Message): void;
|
|
25
|
+
compact(sessionId: string, brain?: any): Promise<void>;
|
|
26
|
+
prune(maxAge: number): number;
|
|
27
|
+
getLineage(sessionId: string): Session[];
|
|
28
|
+
fork(sessionId: string): Session;
|
|
29
|
+
export(sessionId: string): string;
|
|
30
|
+
save(): void;
|
|
31
|
+
load(): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=session-manager.d.ts.map
|