dirac-lang 0.1.60 → 0.1.61

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.
@@ -0,0 +1,226 @@
1
+ import {
2
+ SessionServer,
3
+ getSocketPath,
4
+ isSessionRunning
5
+ } from "./chunk-AU3YU63U.js";
6
+ import "./chunk-ZAA6R2TC.js";
7
+ import "./chunk-HRHAMPOB.js";
8
+ import "./chunk-NKA6ZJDV.js";
9
+ import "./chunk-3UW6GWYQ.js";
10
+
11
+ // src/agent.ts
12
+ import fs from "fs";
13
+ import path from "path";
14
+ import os from "os";
15
+ import { spawn } from "child_process";
16
+ var AGENT_DIR = path.join(os.homedir(), ".dirac");
17
+ var PID_FILE = path.join(AGENT_DIR, "session.pid");
18
+ var LOG_FILE = path.join(AGENT_DIR, "agent.log");
19
+ var AgentCLI = class {
20
+ async start() {
21
+ if (isSessionRunning()) {
22
+ console.log("Agent is already running");
23
+ const pid = this.getRunningPid();
24
+ if (pid) {
25
+ console.log(`PID: ${pid}`);
26
+ console.log(`Socket: ${getSocketPath()}`);
27
+ console.log(`Logs: ${LOG_FILE}`);
28
+ }
29
+ return;
30
+ }
31
+ if (!fs.existsSync(AGENT_DIR)) {
32
+ fs.mkdirSync(AGENT_DIR, { recursive: true });
33
+ }
34
+ console.log("Starting DIRAC agent...");
35
+ const logFd = fs.openSync(LOG_FILE, "a");
36
+ const child = spawn(
37
+ process.argv[0],
38
+ // node executable
39
+ [process.argv[1], "agent", "daemon"],
40
+ // dirac agent daemon
41
+ {
42
+ detached: true,
43
+ stdio: ["ignore", logFd, logFd],
44
+ // Redirect stdout/stderr to log file
45
+ cwd: process.cwd()
46
+ }
47
+ );
48
+ fs.closeSync(logFd);
49
+ child.unref();
50
+ let attempts = 0;
51
+ const maxAttempts = 10;
52
+ while (attempts < maxAttempts) {
53
+ await new Promise((resolve) => setTimeout(resolve, 500));
54
+ if (isSessionRunning()) {
55
+ console.log("\u2713 Agent started successfully");
56
+ console.log(` PID: ${child.pid}`);
57
+ console.log(` Socket: ${getSocketPath()}`);
58
+ console.log(` Logs: ${LOG_FILE}`);
59
+ console.log("");
60
+ console.log("Connect with: dirac shell --agent");
61
+ return;
62
+ }
63
+ attempts++;
64
+ }
65
+ console.error("\u2717 Failed to start agent");
66
+ console.error("Check logs:", LOG_FILE);
67
+ process.exit(1);
68
+ }
69
+ async stop() {
70
+ const pid = this.getRunningPid();
71
+ if (!pid) {
72
+ console.log("Agent is not running");
73
+ return;
74
+ }
75
+ console.log(`Stopping agent (PID: ${pid})...`);
76
+ try {
77
+ process.kill(pid, "SIGTERM");
78
+ let attempts = 0;
79
+ while (attempts < 10) {
80
+ await new Promise((resolve) => setTimeout(resolve, 500));
81
+ try {
82
+ process.kill(pid, 0);
83
+ attempts++;
84
+ } catch {
85
+ console.log("\u2713 Agent stopped");
86
+ this.cleanup();
87
+ return;
88
+ }
89
+ }
90
+ console.log("Agent did not stop gracefully, forcing...");
91
+ process.kill(pid, "SIGKILL");
92
+ this.cleanup();
93
+ console.log("\u2713 Agent stopped (forced)");
94
+ } catch (error) {
95
+ if (error.code === "ESRCH") {
96
+ console.log("Agent was not running");
97
+ this.cleanup();
98
+ } else {
99
+ console.error("Error stopping agent:", error.message);
100
+ process.exit(1);
101
+ }
102
+ }
103
+ }
104
+ async status() {
105
+ const pid = this.getRunningPid();
106
+ if (!pid) {
107
+ console.log("Status: NOT RUNNING");
108
+ return;
109
+ }
110
+ try {
111
+ process.kill(pid, 0);
112
+ console.log("Status: RUNNING");
113
+ console.log(`PID: ${pid}`);
114
+ console.log(`Socket: ${getSocketPath()}`);
115
+ console.log(`Logs: ${LOG_FILE}`);
116
+ if (fs.existsSync(PID_FILE)) {
117
+ const stats = fs.statSync(PID_FILE);
118
+ const uptime = Date.now() - stats.mtimeMs;
119
+ console.log(`Uptime: ${this.formatUptime(uptime)}`);
120
+ }
121
+ } catch (error) {
122
+ if (error.code === "ESRCH") {
123
+ console.log("Status: NOT RUNNING (stale PID file)");
124
+ this.cleanup();
125
+ } else {
126
+ throw error;
127
+ }
128
+ }
129
+ }
130
+ async restart() {
131
+ console.log("Restarting agent...");
132
+ await this.stop();
133
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
134
+ await this.start();
135
+ }
136
+ async logs(follow = false) {
137
+ if (!fs.existsSync(LOG_FILE)) {
138
+ console.log("No logs found");
139
+ return;
140
+ }
141
+ if (follow) {
142
+ const { spawn: spawn2 } = await import("child_process");
143
+ const tail = spawn2("tail", ["-f", LOG_FILE], {
144
+ stdio: "inherit"
145
+ });
146
+ process.on("SIGINT", () => {
147
+ tail.kill();
148
+ process.exit(0);
149
+ });
150
+ } else {
151
+ const content = fs.readFileSync(LOG_FILE, "utf-8");
152
+ const lines = content.split("\n");
153
+ const lastLines = lines.slice(-50);
154
+ console.log(lastLines.join("\n"));
155
+ }
156
+ }
157
+ getRunningPid() {
158
+ if (!fs.existsSync(PID_FILE)) {
159
+ return null;
160
+ }
161
+ try {
162
+ const pidStr = fs.readFileSync(PID_FILE, "utf-8").trim();
163
+ return parseInt(pidStr, 10);
164
+ } catch {
165
+ return null;
166
+ }
167
+ }
168
+ cleanup() {
169
+ if (fs.existsSync(PID_FILE)) {
170
+ fs.unlinkSync(PID_FILE);
171
+ }
172
+ }
173
+ formatUptime(ms) {
174
+ const seconds = Math.floor(ms / 1e3);
175
+ const minutes = Math.floor(seconds / 60);
176
+ const hours = Math.floor(minutes / 60);
177
+ const days = Math.floor(hours / 24);
178
+ if (days > 0) return `${days}d ${hours % 24}h`;
179
+ if (hours > 0) return `${hours}h ${minutes % 60}m`;
180
+ if (minutes > 0) return `${minutes}m`;
181
+ return `${seconds}s`;
182
+ }
183
+ };
184
+ async function runAgentDaemon() {
185
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Starting DIRAC agent daemon`);
186
+ let config = {};
187
+ try {
188
+ const fs2 = await import("fs");
189
+ const path2 = await import("path");
190
+ const yaml = await import("js-yaml");
191
+ const configPath = path2.default.resolve(process.cwd(), "config.yml");
192
+ if (fs2.default.existsSync(configPath)) {
193
+ const configData = yaml.default.load(fs2.default.readFileSync(configPath, "utf-8"));
194
+ config = {
195
+ llmProvider: configData.llmProvider,
196
+ llmModel: configData.llmModel,
197
+ customLLMUrl: configData.customLLMUrl,
198
+ initScript: configData.initScript
199
+ };
200
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Loaded config: LLM=${config.llmProvider}/${config.llmModel}`);
201
+ }
202
+ } catch (err) {
203
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] No config.yml found, using defaults`);
204
+ }
205
+ const server = new SessionServer(config);
206
+ try {
207
+ await server.start();
208
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Agent daemon started successfully`);
209
+ const shutdown = async () => {
210
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] Shutting down agent daemon`);
211
+ await server.shutdown();
212
+ process.exit(0);
213
+ };
214
+ process.on("SIGTERM", shutdown);
215
+ process.on("SIGINT", shutdown);
216
+ await new Promise(() => {
217
+ });
218
+ } catch (error) {
219
+ console.error(`[${(/* @__PURE__ */ new Date()).toISOString()}] Failed to start agent:`, error);
220
+ process.exit(1);
221
+ }
222
+ }
223
+ export {
224
+ AgentCLI,
225
+ runAgentDaemon
226
+ };
@@ -0,0 +1,208 @@
1
+ import {
2
+ integrate
3
+ } from "./chunk-ZAA6R2TC.js";
4
+ import {
5
+ DiracParser
6
+ } from "./chunk-HRHAMPOB.js";
7
+ import {
8
+ createSession
9
+ } from "./chunk-3UW6GWYQ.js";
10
+
11
+ // src/session-server.ts
12
+ import net from "net";
13
+ import fs from "fs";
14
+ import path from "path";
15
+ import os from "os";
16
+ var SOCKET_DIR = path.join(os.homedir(), ".dirac");
17
+ var SOCKET_PATH = path.join(SOCKET_DIR, "session.sock");
18
+ var PID_PATH = path.join(SOCKET_DIR, "session.pid");
19
+ var SessionServer = class {
20
+ server;
21
+ session;
22
+ clients = /* @__PURE__ */ new Map();
23
+ clientIdCounter = 0;
24
+ constructor(config) {
25
+ this.session = createSession(config || {});
26
+ this.server = net.createServer(this.handleConnection.bind(this));
27
+ }
28
+ async start() {
29
+ if (!fs.existsSync(SOCKET_DIR)) {
30
+ fs.mkdirSync(SOCKET_DIR, { recursive: true });
31
+ }
32
+ if (fs.existsSync(SOCKET_PATH)) {
33
+ fs.unlinkSync(SOCKET_PATH);
34
+ }
35
+ return new Promise((resolve, reject) => {
36
+ this.server.listen(SOCKET_PATH, () => {
37
+ console.log(`[session-server] Listening on ${SOCKET_PATH}`);
38
+ fs.writeFileSync(PID_PATH, process.pid.toString());
39
+ fs.chmodSync(SOCKET_PATH, 384);
40
+ resolve();
41
+ });
42
+ this.server.on("error", (error) => {
43
+ console.error("[session-server] Error:", error);
44
+ reject(error);
45
+ });
46
+ });
47
+ }
48
+ handleConnection(socket) {
49
+ const clientId = `client-${++this.clientIdCounter}`;
50
+ const client = { id: clientId, socket };
51
+ this.clients.set(clientId, client);
52
+ console.log(`[session-server] Client connected: ${clientId}`);
53
+ let buffer = "";
54
+ socket.on("data", async (data) => {
55
+ buffer += data.toString();
56
+ const lines = buffer.split("\n");
57
+ buffer = lines.pop() || "";
58
+ for (const line of lines) {
59
+ if (!line.trim()) continue;
60
+ try {
61
+ const message = JSON.parse(line);
62
+ await this.handleMessage(client, message);
63
+ } catch (error) {
64
+ this.sendError(client, `Invalid message: ${error}`);
65
+ }
66
+ }
67
+ });
68
+ socket.on("end", () => {
69
+ console.log(`[session-server] Client disconnected: ${clientId}`);
70
+ this.clients.delete(clientId);
71
+ });
72
+ socket.on("error", (error) => {
73
+ console.error(`[session-server] Client error (${clientId}):`, error);
74
+ this.clients.delete(clientId);
75
+ });
76
+ this.sendResponse(client, {
77
+ type: "welcome",
78
+ sessionId: clientId,
79
+ message: "Connected to DIRAC session"
80
+ });
81
+ }
82
+ async handleMessage(client, message) {
83
+ const { type, data } = message;
84
+ switch (type) {
85
+ case "execute":
86
+ await this.executeCommand(client, data.command);
87
+ break;
88
+ case "getVars":
89
+ this.sendResponse(client, {
90
+ type: "vars",
91
+ data: Object.keys(this.session.variables)
92
+ });
93
+ break;
94
+ case "getState":
95
+ this.sendResponse(client, {
96
+ type: "state",
97
+ data: {
98
+ variables: this.session.variables,
99
+ subroutines: this.session.subroutines,
100
+ varBoundary: this.session.varBoundary,
101
+ subBoundary: this.session.subBoundary
102
+ }
103
+ });
104
+ break;
105
+ case "shutdown":
106
+ this.sendResponse(client, {
107
+ type: "shutdown",
108
+ message: "Server shutting down"
109
+ });
110
+ await this.shutdown();
111
+ break;
112
+ default:
113
+ this.sendError(client, `Unknown message type: ${type}`);
114
+ }
115
+ }
116
+ async executeCommand(client, command) {
117
+ try {
118
+ this.session.output = [];
119
+ const parser = new DiracParser();
120
+ const ast = parser.parse(command);
121
+ await integrate(this.session, ast);
122
+ const output = this.session.output.join("");
123
+ this.sendResponse(client, {
124
+ type: "output",
125
+ data: output
126
+ });
127
+ } catch (error) {
128
+ this.sendError(client, error.message);
129
+ }
130
+ }
131
+ sendResponse(client, response) {
132
+ try {
133
+ client.socket.write(JSON.stringify(response) + "\n");
134
+ } catch (error) {
135
+ console.error(`[session-server] Failed to send response:`, error);
136
+ }
137
+ }
138
+ sendError(client, message) {
139
+ this.sendResponse(client, {
140
+ type: "error",
141
+ message
142
+ });
143
+ }
144
+ async shutdown() {
145
+ console.log("[session-server] Shutting down...");
146
+ for (const client of this.clients.values()) {
147
+ client.socket.end();
148
+ }
149
+ this.clients.clear();
150
+ return new Promise((resolve) => {
151
+ this.server.close(() => {
152
+ if (fs.existsSync(SOCKET_PATH)) {
153
+ fs.unlinkSync(SOCKET_PATH);
154
+ }
155
+ if (fs.existsSync(PID_PATH)) {
156
+ fs.unlinkSync(PID_PATH);
157
+ }
158
+ console.log("[session-server] Shutdown complete");
159
+ resolve();
160
+ });
161
+ });
162
+ }
163
+ };
164
+ function isSessionRunning() {
165
+ if (!fs.existsSync(PID_PATH)) {
166
+ return false;
167
+ }
168
+ try {
169
+ const pid = parseInt(fs.readFileSync(PID_PATH, "utf-8").trim(), 10);
170
+ process.kill(pid, 0);
171
+ return true;
172
+ } catch (error) {
173
+ if (fs.existsSync(PID_PATH)) fs.unlinkSync(PID_PATH);
174
+ try {
175
+ if (fs.existsSync(SOCKET_PATH)) fs.unlinkSync(SOCKET_PATH);
176
+ } catch (e) {
177
+ }
178
+ return false;
179
+ }
180
+ }
181
+ function getSocketPath() {
182
+ return SOCKET_PATH;
183
+ }
184
+ if (import.meta.url === `file://${process.argv[1]}`) {
185
+ const server = new SessionServer();
186
+ server.start().then(() => {
187
+ console.log("[session-server] Server started successfully");
188
+ process.on("SIGINT", async () => {
189
+ console.log("\n[session-server] Received SIGINT, shutting down...");
190
+ await server.shutdown();
191
+ process.exit(0);
192
+ });
193
+ process.on("SIGTERM", async () => {
194
+ console.log("\n[session-server] Received SIGTERM, shutting down...");
195
+ await server.shutdown();
196
+ process.exit(0);
197
+ });
198
+ }).catch((error) => {
199
+ console.error("[session-server] Failed to start:", error);
200
+ process.exit(1);
201
+ });
202
+ }
203
+
204
+ export {
205
+ SessionServer,
206
+ isSessionRunning,
207
+ getSocketPath
208
+ };
package/dist/cli.js CHANGED
@@ -75,9 +75,22 @@ async function main() {
75
75
  if (args.includes("--help") || args.includes("-h")) {
76
76
  console.log("Usage: dirac <file.di|file.bk>");
77
77
  console.log(" dirac shell [options]");
78
+ console.log(" dirac agent <command>");
78
79
  console.log("");
79
80
  console.log("Commands:");
80
81
  console.log(" shell Start interactive shell (REPL)");
82
+ console.log(" shell --agent Connect shell to running agent daemon");
83
+ console.log(" agent start Start persistent agent daemon");
84
+ console.log(" agent stop Stop agent daemon");
85
+ console.log(" agent status Check agent status");
86
+ console.log(" agent restart Restart agent daemon");
87
+ console.log(" agent logs Show agent logs");
88
+ console.log(" shell --daemon Start shell with persistent daemon (experimental)");
89
+ console.log("");
90
+ console.log("Shell tips:");
91
+ console.log(" Press Ctrl-Z to suspend shell, then `bg` to run in background");
92
+ console.log(" Use `fg` to bring it back to foreground");
93
+ console.log(" Cron jobs and run-at tasks continue running in background");
81
94
  console.log("");
82
95
  console.log("File formats:");
83
96
  console.log(" .di XML notation (verbose)");
@@ -98,13 +111,54 @@ async function main() {
98
111
  console.log(package_default.version);
99
112
  process.exit(0);
100
113
  }
114
+ if (args[0] === "agent") {
115
+ const subcommand = args[1];
116
+ if (subcommand === "daemon") {
117
+ const { runAgentDaemon } = await import("./agent-OXQZBLNQ.js");
118
+ await runAgentDaemon();
119
+ return;
120
+ }
121
+ const { AgentCLI } = await import("./agent-OXQZBLNQ.js");
122
+ const agent = new AgentCLI();
123
+ switch (subcommand) {
124
+ case "start":
125
+ await agent.start();
126
+ break;
127
+ case "stop":
128
+ await agent.stop();
129
+ break;
130
+ case "status":
131
+ await agent.status();
132
+ break;
133
+ case "restart":
134
+ await agent.restart();
135
+ break;
136
+ case "logs":
137
+ const follow = args.includes("-f") || args.includes("--follow");
138
+ await agent.logs(follow);
139
+ break;
140
+ default:
141
+ console.error("Unknown agent command:", subcommand);
142
+ console.error("Available commands: start, stop, status, restart, logs");
143
+ process.exit(1);
144
+ }
145
+ return;
146
+ }
101
147
  if (args[0] === "shell") {
102
- const { DiracShell } = await import("./shell-WFLXZW3I.js");
148
+ const { DiracShell } = await import("./shell-OFBL57OA.js");
149
+ const { SessionServer, isSessionRunning, getSocketPath } = await import("./session-server-QZN2RMYD.js");
150
+ const { SessionClient } = await import("./session-client-3VTC5MLO.js");
151
+ const daemonMode = args.includes("--daemon") || args.includes("-d");
152
+ const agentMode = args.includes("--agent") || args.includes("-a");
103
153
  const shellConfig = { debug: false };
104
154
  for (let i = 1; i < args.length; i++) {
105
155
  const arg = args[i];
106
156
  if (arg === "--debug") {
107
157
  shellConfig.debug = true;
158
+ } else if (arg === "--daemon" || arg === "-d") {
159
+ continue;
160
+ } else if (arg === "--agent" || arg === "-a") {
161
+ continue;
108
162
  } else if ((arg === "-f" || arg === "--config") && i + 1 < args.length) {
109
163
  const configPath = resolve(args[++i]);
110
164
  if (fs.existsSync(configPath)) {
@@ -131,10 +185,59 @@ async function main() {
131
185
  }
132
186
  }
133
187
  }
188
+ if (agentMode) {
189
+ if (!isSessionRunning()) {
190
+ console.error("Error: No agent is running");
191
+ console.error("Start the agent first with: dirac agent start");
192
+ process.exit(1);
193
+ }
194
+ console.log("Connecting to agent...");
195
+ const client = new SessionClient({ socketPath: getSocketPath() });
196
+ client.on("error", (error) => {
197
+ console.error("Agent error:", error);
198
+ });
199
+ try {
200
+ await client.connect();
201
+ console.log("Connected to agent at", getSocketPath());
202
+ console.log("Session state is persistent across disconnects");
203
+ console.log("");
204
+ const shell2 = new DiracShell(shellConfig);
205
+ shell2.setClient(client);
206
+ process.on("SIGINT", async () => {
207
+ await client.disconnect();
208
+ process.exit(0);
209
+ });
210
+ await shell2.start();
211
+ } catch (error) {
212
+ console.error("Failed to connect to agent:", error);
213
+ process.exit(1);
214
+ }
215
+ return;
216
+ }
217
+ if (daemonMode) {
218
+ console.log("Note: Daemon mode is under development.");
219
+ console.log("For now, use Ctrl-Z + bg to background the shell.");
220
+ console.log("");
221
+ }
134
222
  const shell = new DiracShell(shellConfig);
135
223
  await shell.start();
136
224
  return;
137
225
  }
226
+ if (args[0] === "daemon") {
227
+ const { SessionServer } = await import("./session-server-QZN2RMYD.js");
228
+ const server = new SessionServer();
229
+ await server.start();
230
+ console.log("Session daemon started");
231
+ process.on("SIGINT", async () => {
232
+ await server.shutdown();
233
+ process.exit(0);
234
+ });
235
+ process.on("SIGTERM", async () => {
236
+ await server.shutdown();
237
+ process.exit(0);
238
+ });
239
+ return;
240
+ }
138
241
  if (args.length === 0) {
139
242
  console.error("Usage: dirac <file.di|file.bk>");
140
243
  console.error(" dirac shell [options]");
@@ -0,0 +1,177 @@
1
+ // src/session-client.ts
2
+ import net from "net";
3
+ import { EventEmitter } from "events";
4
+ var SessionClient = class extends EventEmitter {
5
+ socket = null;
6
+ buffer = "";
7
+ connected = false;
8
+ options;
9
+ constructor(options) {
10
+ super();
11
+ this.options = {
12
+ autoReconnect: false,
13
+ reconnectDelay: 1e3,
14
+ ...options
15
+ };
16
+ }
17
+ async connect() {
18
+ return new Promise((resolve, reject) => {
19
+ this.socket = net.connect(this.options.socketPath);
20
+ this.socket.on("connect", () => {
21
+ this.emit("socket-connected");
22
+ });
23
+ this.socket.on("data", (data) => {
24
+ this.buffer += data.toString();
25
+ const lines = this.buffer.split("\n");
26
+ this.buffer = lines.pop() || "";
27
+ for (const line of lines) {
28
+ if (!line.trim()) continue;
29
+ try {
30
+ const message = JSON.parse(line);
31
+ this.handleMessage(message);
32
+ } catch (error) {
33
+ this.emit("error", new Error(`Invalid message: ${error}`));
34
+ }
35
+ }
36
+ });
37
+ this.socket.on("end", () => {
38
+ this.connected = false;
39
+ this.emit("disconnected");
40
+ if (this.options.autoReconnect) {
41
+ setTimeout(() => this.connect(), this.options.reconnectDelay);
42
+ }
43
+ });
44
+ this.socket.on("error", (error) => {
45
+ this.connected = false;
46
+ reject(error);
47
+ this.emit("error", error);
48
+ });
49
+ this.once("welcome", () => {
50
+ this.connected = true;
51
+ resolve();
52
+ });
53
+ });
54
+ }
55
+ handleMessage(message) {
56
+ const { type, data, message: msg } = message;
57
+ switch (type) {
58
+ case "welcome":
59
+ this.emit("welcome", msg);
60
+ break;
61
+ case "output":
62
+ this.emit("output", data);
63
+ break;
64
+ case "error":
65
+ this.emit("error", new Error(msg || data));
66
+ break;
67
+ case "vars":
68
+ this.emit("vars", data);
69
+ break;
70
+ case "state":
71
+ this.emit("state", data);
72
+ break;
73
+ case "shutdown":
74
+ this.emit("shutdown");
75
+ break;
76
+ default:
77
+ this.emit("message", message);
78
+ }
79
+ }
80
+ async execute(command) {
81
+ return new Promise((resolve, reject) => {
82
+ if (!this.socket) {
83
+ reject(new Error("Not connected to session: socket is null"));
84
+ return;
85
+ }
86
+ if (!this.connected) {
87
+ reject(new Error("Not connected to session: connected flag is false"));
88
+ return;
89
+ }
90
+ this.send({ type: "execute", data: { command } });
91
+ const timeout = setTimeout(() => {
92
+ reject(new Error("Execution timeout"));
93
+ }, 3e4);
94
+ const onOutput = (output) => {
95
+ clearTimeout(timeout);
96
+ this.off("error", onError);
97
+ resolve(output);
98
+ };
99
+ const onError = (error) => {
100
+ clearTimeout(timeout);
101
+ this.off("output", onOutput);
102
+ reject(error);
103
+ };
104
+ this.once("output", onOutput);
105
+ this.once("error", onError);
106
+ });
107
+ }
108
+ async getVars() {
109
+ return new Promise((resolve, reject) => {
110
+ if (!this.connected || !this.socket) {
111
+ reject(new Error("Not connected to session"));
112
+ return;
113
+ }
114
+ this.send({ type: "getVars" });
115
+ const timeout = setTimeout(() => {
116
+ reject(new Error("Timeout getting variables"));
117
+ }, 5e3);
118
+ const onVars = (vars) => {
119
+ clearTimeout(timeout);
120
+ resolve(vars);
121
+ };
122
+ this.once("vars", onVars);
123
+ });
124
+ }
125
+ async getState() {
126
+ return new Promise((resolve, reject) => {
127
+ if (!this.socket) {
128
+ reject(new Error("Not connected to session: socket is null"));
129
+ return;
130
+ }
131
+ if (!this.connected) {
132
+ reject(new Error("Not connected to session: connected flag is false"));
133
+ return;
134
+ }
135
+ this.send({ type: "getState" });
136
+ const timeout = setTimeout(() => {
137
+ reject(new Error("Timeout getting state"));
138
+ }, 5e3);
139
+ const onState = (state) => {
140
+ clearTimeout(timeout);
141
+ resolve(state);
142
+ };
143
+ this.once("state", onState);
144
+ });
145
+ }
146
+ async shutdown() {
147
+ return new Promise((resolve) => {
148
+ if (!this.connected || !this.socket) {
149
+ resolve();
150
+ return;
151
+ }
152
+ this.send({ type: "shutdown" });
153
+ this.once("shutdown", () => {
154
+ resolve();
155
+ });
156
+ });
157
+ }
158
+ send(message) {
159
+ if (!this.socket || !this.connected) {
160
+ throw new Error("Not connected to session");
161
+ }
162
+ this.socket.write(JSON.stringify(message) + "\n");
163
+ }
164
+ disconnect() {
165
+ if (this.socket) {
166
+ this.socket.end();
167
+ this.socket = null;
168
+ }
169
+ this.connected = false;
170
+ }
171
+ isConnected() {
172
+ return this.connected;
173
+ }
174
+ };
175
+ export {
176
+ SessionClient
177
+ };
@@ -0,0 +1,14 @@
1
+ import {
2
+ SessionServer,
3
+ getSocketPath,
4
+ isSessionRunning
5
+ } from "./chunk-AU3YU63U.js";
6
+ import "./chunk-ZAA6R2TC.js";
7
+ import "./chunk-HRHAMPOB.js";
8
+ import "./chunk-NKA6ZJDV.js";
9
+ import "./chunk-3UW6GWYQ.js";
10
+ export {
11
+ SessionServer,
12
+ getSocketPath,
13
+ isSessionRunning
14
+ };
@@ -23,6 +23,7 @@ var HISTORY_FILE = path.join(os.homedir(), ".dirac_history");
23
23
  var MAX_HISTORY = 1e3;
24
24
  var DiracShell = class {
25
25
  session;
26
+ client = null;
26
27
  braketParser;
27
28
  xmlParser;
28
29
  rl;
@@ -45,6 +46,12 @@ var DiracShell = class {
45
46
  this.loadHistory();
46
47
  this.setupHandlers();
47
48
  }
49
+ /**
50
+ * Set client for daemon mode
51
+ */
52
+ setClient(client) {
53
+ this.client = client;
54
+ }
48
55
  completer(line) {
49
56
  const attrMatch = line.match(/\|([a-z0-9_-]+)\s+.*?([a-z0-9_-]*)$/i);
50
57
  if (attrMatch) {
@@ -150,6 +157,9 @@ var DiracShell = class {
150
157
  });
151
158
  this.rl.on("close", () => {
152
159
  this.saveHistory();
160
+ if (this.client) {
161
+ this.client.disconnect();
162
+ }
153
163
  import("./schedule-QZ5U3YBS.js").then(({ stopAllScheduledTasks }) => {
154
164
  stopAllScheduledTasks();
155
165
  console.log("\nGoodbye!");
@@ -249,6 +259,17 @@ var DiracShell = class {
249
259
  this.inputBuffer = [];
250
260
  this.baseIndent = null;
251
261
  try {
262
+ if (this.client) {
263
+ const xml2 = this.braketParser.parse(input);
264
+ if (this.config.debug) {
265
+ console.log("[Debug] Sending to agent:\n", xml2);
266
+ }
267
+ const output = await this.client.execute(xml2);
268
+ if (output) {
269
+ console.log(output);
270
+ }
271
+ return;
272
+ }
252
273
  this.session.output = [];
253
274
  const xml = this.braketParser.parse(input);
254
275
  if (this.config.debug) {
@@ -321,29 +342,56 @@ Examples:
321
342
  `);
322
343
  break;
323
344
  case "vars":
324
- if (this.session.variables.length === 0) {
325
- console.log("No variables defined");
326
- } else {
327
- console.log("Variables:");
328
- for (const v of this.session.variables) {
329
- if (v.visible) {
330
- console.log(` ${v.name} = ${JSON.stringify(v.value)}`);
345
+ try {
346
+ let variables;
347
+ if (this.client) {
348
+ const state = await this.client.getState();
349
+ variables = state.variables || [];
350
+ } else {
351
+ variables = this.session.variables;
352
+ }
353
+ if (variables.length === 0) {
354
+ console.log("No variables defined");
355
+ } else {
356
+ console.log("Variables:");
357
+ for (const v of variables) {
358
+ if (v.visible) {
359
+ console.log(` ${v.name} = ${JSON.stringify(v.value)}`);
360
+ }
331
361
  }
332
362
  }
363
+ } catch (error) {
364
+ console.error("Error getting variables:", error instanceof Error ? error.message : String(error));
333
365
  }
334
366
  break;
335
367
  case "subs":
336
- if (this.session.subroutines.length === 0) {
337
- console.log("No subroutines defined");
338
- } else {
339
- console.log("Subroutines:");
340
- for (const s of this.session.subroutines) {
341
- const params = s.parameters?.map((p) => p.name).join(", ") || "";
342
- console.log(` ${s.name}(${params})`);
343
- if (s.description) {
344
- console.log(` ${s.description}`);
368
+ try {
369
+ let subroutines;
370
+ if (this.client) {
371
+ const state = await this.client.getState();
372
+ console.log("State received:", JSON.stringify(state, null, 2).substring(0, 500));
373
+ subroutines = state.subroutines || [];
374
+ } else {
375
+ subroutines = this.session.subroutines;
376
+ }
377
+ if (!Array.isArray(subroutines)) {
378
+ console.error("Error: subroutines is not an array, it is:", typeof subroutines);
379
+ break;
380
+ }
381
+ if (subroutines.length === 0) {
382
+ console.log("No subroutines defined");
383
+ } else {
384
+ console.log("Subroutines:");
385
+ for (const s of subroutines) {
386
+ const params = s.parameters?.map((p) => p.name).join(", ") || "";
387
+ console.log(` ${s.name}(${params})`);
388
+ if (s.description) {
389
+ console.log(` ${s.description}`);
390
+ }
345
391
  }
346
392
  }
393
+ } catch (error) {
394
+ console.error("Error getting subroutines:", error instanceof Error ? error.message : String(error));
347
395
  }
348
396
  break;
349
397
  case "clear":
@@ -709,9 +757,14 @@ Examples:
709
757
  }
710
758
  console.log(`Loading init script: ${scriptPath}`);
711
759
  const scriptContent = fs.readFileSync(resolvedPath, "utf-8");
712
- const xml = this.braketParser.parse(scriptContent);
713
- const ast = this.xmlParser.parse(xml);
714
- await integrate(this.session, ast);
760
+ if (this.client) {
761
+ const xml = this.braketParser.parse(scriptContent);
762
+ await this.client.execute(xml);
763
+ } else {
764
+ const xml = this.braketParser.parse(scriptContent);
765
+ const ast = this.xmlParser.parse(xml);
766
+ await integrate(this.session, ast);
767
+ }
715
768
  console.log(`Init script loaded.
716
769
  `);
717
770
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirac-lang",
3
- "version": "0.1.60",
3
+ "version": "0.1.61",
4
4
  "description": "LLM-Augmented Declarative Execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",