chatroom-cli 1.0.66 → 1.0.68
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/dist/index.js +324 -293
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9915,6 +9915,290 @@ var init_auth_logout = __esm(() => {
|
|
|
9915
9915
|
init_storage();
|
|
9916
9916
|
});
|
|
9917
9917
|
|
|
9918
|
+
// src/infrastructure/machine/types.ts
|
|
9919
|
+
var AGENT_HARNESSES, AGENT_HARNESS_COMMANDS, MACHINE_CONFIG_VERSION = "1";
|
|
9920
|
+
var init_types = __esm(() => {
|
|
9921
|
+
AGENT_HARNESSES = ["opencode"];
|
|
9922
|
+
AGENT_HARNESS_COMMANDS = {
|
|
9923
|
+
opencode: "opencode"
|
|
9924
|
+
};
|
|
9925
|
+
});
|
|
9926
|
+
|
|
9927
|
+
// src/infrastructure/machine/detection.ts
|
|
9928
|
+
import { execSync } from "node:child_process";
|
|
9929
|
+
function commandExists(command) {
|
|
9930
|
+
try {
|
|
9931
|
+
const checkCommand = process.platform === "win32" ? `where ${command}` : `which ${command}`;
|
|
9932
|
+
execSync(checkCommand, { stdio: "ignore" });
|
|
9933
|
+
return true;
|
|
9934
|
+
} catch {
|
|
9935
|
+
return false;
|
|
9936
|
+
}
|
|
9937
|
+
}
|
|
9938
|
+
function parseVersion(versionStr) {
|
|
9939
|
+
const match = versionStr.match(/v?(\d+)\.(\d+)\.(\d+)/);
|
|
9940
|
+
if (!match)
|
|
9941
|
+
return null;
|
|
9942
|
+
const major = parseInt(match[1], 10);
|
|
9943
|
+
const version2 = `${match[1]}.${match[2]}.${match[3]}`;
|
|
9944
|
+
return { version: version2, major };
|
|
9945
|
+
}
|
|
9946
|
+
function detectHarnessVersion(harness) {
|
|
9947
|
+
const versionCommand = HARNESS_VERSION_COMMANDS[harness];
|
|
9948
|
+
if (!versionCommand)
|
|
9949
|
+
return null;
|
|
9950
|
+
try {
|
|
9951
|
+
const output = execSync(versionCommand, {
|
|
9952
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
9953
|
+
timeout: 5000
|
|
9954
|
+
}).toString().trim();
|
|
9955
|
+
return parseVersion(output);
|
|
9956
|
+
} catch {
|
|
9957
|
+
return null;
|
|
9958
|
+
}
|
|
9959
|
+
}
|
|
9960
|
+
function detectHarnessVersions(harnesses) {
|
|
9961
|
+
const versions = {};
|
|
9962
|
+
for (const harness of harnesses) {
|
|
9963
|
+
const version2 = detectHarnessVersion(harness);
|
|
9964
|
+
if (version2) {
|
|
9965
|
+
versions[harness] = version2;
|
|
9966
|
+
}
|
|
9967
|
+
}
|
|
9968
|
+
return versions;
|
|
9969
|
+
}
|
|
9970
|
+
function detectAvailableHarnesses() {
|
|
9971
|
+
const available = [];
|
|
9972
|
+
for (const harness of AGENT_HARNESSES) {
|
|
9973
|
+
const command = AGENT_HARNESS_COMMANDS[harness];
|
|
9974
|
+
if (commandExists(command)) {
|
|
9975
|
+
available.push(harness);
|
|
9976
|
+
}
|
|
9977
|
+
}
|
|
9978
|
+
return available;
|
|
9979
|
+
}
|
|
9980
|
+
var HARNESS_VERSION_COMMANDS;
|
|
9981
|
+
var init_detection = __esm(() => {
|
|
9982
|
+
init_types();
|
|
9983
|
+
HARNESS_VERSION_COMMANDS = {
|
|
9984
|
+
opencode: "opencode --version"
|
|
9985
|
+
};
|
|
9986
|
+
});
|
|
9987
|
+
|
|
9988
|
+
// src/infrastructure/machine/storage.ts
|
|
9989
|
+
import { randomUUID } from "node:crypto";
|
|
9990
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "node:fs";
|
|
9991
|
+
import { homedir as homedir2, hostname as hostname2 } from "node:os";
|
|
9992
|
+
import { join as join3 } from "node:path";
|
|
9993
|
+
function ensureConfigDir2() {
|
|
9994
|
+
if (!existsSync2(CHATROOM_DIR2)) {
|
|
9995
|
+
mkdirSync2(CHATROOM_DIR2, { recursive: true, mode: 448 });
|
|
9996
|
+
}
|
|
9997
|
+
}
|
|
9998
|
+
function getMachineConfigPath() {
|
|
9999
|
+
return join3(CHATROOM_DIR2, MACHINE_FILE);
|
|
10000
|
+
}
|
|
10001
|
+
function loadConfigFile() {
|
|
10002
|
+
const configPath = getMachineConfigPath();
|
|
10003
|
+
if (!existsSync2(configPath)) {
|
|
10004
|
+
return null;
|
|
10005
|
+
}
|
|
10006
|
+
try {
|
|
10007
|
+
const content = readFileSync3(configPath, "utf-8");
|
|
10008
|
+
return JSON.parse(content);
|
|
10009
|
+
} catch (error) {
|
|
10010
|
+
console.warn(`⚠️ Failed to read machine config at ${configPath}: ${error.message}`);
|
|
10011
|
+
console.warn(` The machine will re-register with a new identity on next startup.`);
|
|
10012
|
+
console.warn(` If this is unexpected, check the file for corruption.`);
|
|
10013
|
+
return null;
|
|
10014
|
+
}
|
|
10015
|
+
}
|
|
10016
|
+
function saveConfigFile(configFile) {
|
|
10017
|
+
ensureConfigDir2();
|
|
10018
|
+
const configPath = getMachineConfigPath();
|
|
10019
|
+
const tempPath = `${configPath}.tmp`;
|
|
10020
|
+
const content = JSON.stringify(configFile, null, 2);
|
|
10021
|
+
writeFileSync2(tempPath, content, { encoding: "utf-8", mode: 384 });
|
|
10022
|
+
renameSync(tempPath, configPath);
|
|
10023
|
+
}
|
|
10024
|
+
function loadMachineConfig() {
|
|
10025
|
+
const configFile = loadConfigFile();
|
|
10026
|
+
if (!configFile)
|
|
10027
|
+
return null;
|
|
10028
|
+
const convexUrl = getConvexUrl();
|
|
10029
|
+
return configFile.machines[convexUrl] ?? null;
|
|
10030
|
+
}
|
|
10031
|
+
function saveMachineConfig(config) {
|
|
10032
|
+
const configFile = loadConfigFile() ?? {
|
|
10033
|
+
version: MACHINE_CONFIG_VERSION,
|
|
10034
|
+
machines: {}
|
|
10035
|
+
};
|
|
10036
|
+
const convexUrl = getConvexUrl();
|
|
10037
|
+
configFile.machines[convexUrl] = config;
|
|
10038
|
+
saveConfigFile(configFile);
|
|
10039
|
+
}
|
|
10040
|
+
function createNewEndpointConfig() {
|
|
10041
|
+
const now = new Date().toISOString();
|
|
10042
|
+
const availableHarnesses = detectAvailableHarnesses();
|
|
10043
|
+
return {
|
|
10044
|
+
machineId: randomUUID(),
|
|
10045
|
+
hostname: hostname2(),
|
|
10046
|
+
os: process.platform,
|
|
10047
|
+
registeredAt: now,
|
|
10048
|
+
lastSyncedAt: now,
|
|
10049
|
+
availableHarnesses,
|
|
10050
|
+
harnessVersions: detectHarnessVersions(availableHarnesses),
|
|
10051
|
+
chatroomAgents: {}
|
|
10052
|
+
};
|
|
10053
|
+
}
|
|
10054
|
+
function ensureMachineRegistered() {
|
|
10055
|
+
let config = loadMachineConfig();
|
|
10056
|
+
if (!config) {
|
|
10057
|
+
config = createNewEndpointConfig();
|
|
10058
|
+
saveMachineConfig(config);
|
|
10059
|
+
} else {
|
|
10060
|
+
const now = new Date().toISOString();
|
|
10061
|
+
config.availableHarnesses = detectAvailableHarnesses();
|
|
10062
|
+
config.harnessVersions = detectHarnessVersions(config.availableHarnesses);
|
|
10063
|
+
config.lastSyncedAt = now;
|
|
10064
|
+
config.hostname = hostname2();
|
|
10065
|
+
saveMachineConfig(config);
|
|
10066
|
+
}
|
|
10067
|
+
return {
|
|
10068
|
+
machineId: config.machineId,
|
|
10069
|
+
hostname: config.hostname,
|
|
10070
|
+
os: config.os,
|
|
10071
|
+
availableHarnesses: config.availableHarnesses,
|
|
10072
|
+
harnessVersions: config.harnessVersions
|
|
10073
|
+
};
|
|
10074
|
+
}
|
|
10075
|
+
function getMachineId() {
|
|
10076
|
+
const config = loadMachineConfig();
|
|
10077
|
+
return config?.machineId ?? null;
|
|
10078
|
+
}
|
|
10079
|
+
function updateAgentContext(chatroomId, role, agentType, workingDir) {
|
|
10080
|
+
const config = loadMachineConfig();
|
|
10081
|
+
if (!config) {
|
|
10082
|
+
throw new Error("Machine not registered. Run ensureMachineRegistered() first.");
|
|
10083
|
+
}
|
|
10084
|
+
const now = new Date().toISOString();
|
|
10085
|
+
if (!config.chatroomAgents[chatroomId]) {
|
|
10086
|
+
config.chatroomAgents[chatroomId] = {};
|
|
10087
|
+
}
|
|
10088
|
+
config.chatroomAgents[chatroomId][role] = {
|
|
10089
|
+
agentType,
|
|
10090
|
+
workingDir,
|
|
10091
|
+
lastStartedAt: now
|
|
10092
|
+
};
|
|
10093
|
+
saveMachineConfig(config);
|
|
10094
|
+
}
|
|
10095
|
+
function getAgentContext(chatroomId, role) {
|
|
10096
|
+
const config = loadMachineConfig();
|
|
10097
|
+
if (!config) {
|
|
10098
|
+
return null;
|
|
10099
|
+
}
|
|
10100
|
+
return config.chatroomAgents[chatroomId]?.[role] ?? null;
|
|
10101
|
+
}
|
|
10102
|
+
var CHATROOM_DIR2, MACHINE_FILE = "machine.json";
|
|
10103
|
+
var init_storage2 = __esm(() => {
|
|
10104
|
+
init_detection();
|
|
10105
|
+
init_types();
|
|
10106
|
+
init_client2();
|
|
10107
|
+
CHATROOM_DIR2 = join3(homedir2(), ".chatroom");
|
|
10108
|
+
});
|
|
10109
|
+
|
|
10110
|
+
// src/infrastructure/machine/daemon-state.ts
|
|
10111
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync2 } from "node:fs";
|
|
10112
|
+
import { homedir as homedir3 } from "node:os";
|
|
10113
|
+
import { join as join4 } from "node:path";
|
|
10114
|
+
function agentKey(chatroomId, role) {
|
|
10115
|
+
return `${chatroomId}/${role}`;
|
|
10116
|
+
}
|
|
10117
|
+
function ensureStateDir() {
|
|
10118
|
+
if (!existsSync3(STATE_DIR)) {
|
|
10119
|
+
mkdirSync3(STATE_DIR, { recursive: true, mode: 448 });
|
|
10120
|
+
}
|
|
10121
|
+
}
|
|
10122
|
+
function stateFilePath(machineId) {
|
|
10123
|
+
return join4(STATE_DIR, `${machineId}.json`);
|
|
10124
|
+
}
|
|
10125
|
+
function loadDaemonState(machineId) {
|
|
10126
|
+
const filePath = stateFilePath(machineId);
|
|
10127
|
+
if (!existsSync3(filePath)) {
|
|
10128
|
+
return null;
|
|
10129
|
+
}
|
|
10130
|
+
try {
|
|
10131
|
+
const content = readFileSync4(filePath, "utf-8");
|
|
10132
|
+
return JSON.parse(content);
|
|
10133
|
+
} catch {
|
|
10134
|
+
return null;
|
|
10135
|
+
}
|
|
10136
|
+
}
|
|
10137
|
+
function saveDaemonState(state) {
|
|
10138
|
+
ensureStateDir();
|
|
10139
|
+
const filePath = stateFilePath(state.machineId);
|
|
10140
|
+
const tempPath = `${filePath}.tmp`;
|
|
10141
|
+
const content = JSON.stringify(state, null, 2);
|
|
10142
|
+
writeFileSync3(tempPath, content, { encoding: "utf-8", mode: 384 });
|
|
10143
|
+
renameSync2(tempPath, filePath);
|
|
10144
|
+
}
|
|
10145
|
+
function loadOrCreate(machineId) {
|
|
10146
|
+
return loadDaemonState(machineId) ?? {
|
|
10147
|
+
version: STATE_VERSION,
|
|
10148
|
+
machineId,
|
|
10149
|
+
updatedAt: new Date().toISOString(),
|
|
10150
|
+
agents: {}
|
|
10151
|
+
};
|
|
10152
|
+
}
|
|
10153
|
+
function persistAgentPid(machineId, chatroomId, role, pid, harness) {
|
|
10154
|
+
const state = loadOrCreate(machineId);
|
|
10155
|
+
state.agents[agentKey(chatroomId, role)] = {
|
|
10156
|
+
pid,
|
|
10157
|
+
harness,
|
|
10158
|
+
startedAt: new Date().toISOString()
|
|
10159
|
+
};
|
|
10160
|
+
state.updatedAt = new Date().toISOString();
|
|
10161
|
+
saveDaemonState(state);
|
|
10162
|
+
}
|
|
10163
|
+
function clearAgentPid(machineId, chatroomId, role) {
|
|
10164
|
+
const state = loadDaemonState(machineId);
|
|
10165
|
+
if (!state)
|
|
10166
|
+
return;
|
|
10167
|
+
const key = agentKey(chatroomId, role);
|
|
10168
|
+
if (!(key in state.agents))
|
|
10169
|
+
return;
|
|
10170
|
+
delete state.agents[key];
|
|
10171
|
+
state.updatedAt = new Date().toISOString();
|
|
10172
|
+
saveDaemonState(state);
|
|
10173
|
+
}
|
|
10174
|
+
function listAgentEntries(machineId) {
|
|
10175
|
+
const state = loadDaemonState(machineId);
|
|
10176
|
+
if (!state)
|
|
10177
|
+
return [];
|
|
10178
|
+
const results = [];
|
|
10179
|
+
for (const [key, entry] of Object.entries(state.agents)) {
|
|
10180
|
+
const separatorIndex = key.lastIndexOf("/");
|
|
10181
|
+
if (separatorIndex === -1)
|
|
10182
|
+
continue;
|
|
10183
|
+
const chatroomId = key.substring(0, separatorIndex);
|
|
10184
|
+
const role = key.substring(separatorIndex + 1);
|
|
10185
|
+
results.push({ chatroomId, role, entry });
|
|
10186
|
+
}
|
|
10187
|
+
return results;
|
|
10188
|
+
}
|
|
10189
|
+
var CHATROOM_DIR3, STATE_DIR, STATE_VERSION = "1";
|
|
10190
|
+
var init_daemon_state = __esm(() => {
|
|
10191
|
+
CHATROOM_DIR3 = join4(homedir3(), ".chatroom");
|
|
10192
|
+
STATE_DIR = join4(CHATROOM_DIR3, "machines", "state");
|
|
10193
|
+
});
|
|
10194
|
+
|
|
10195
|
+
// src/infrastructure/machine/index.ts
|
|
10196
|
+
var init_machine = __esm(() => {
|
|
10197
|
+
init_types();
|
|
10198
|
+
init_storage2();
|
|
10199
|
+
init_daemon_state();
|
|
10200
|
+
});
|
|
10201
|
+
|
|
9918
10202
|
// src/commands/auth-status.ts
|
|
9919
10203
|
var exports_auth_status = {};
|
|
9920
10204
|
__export(exports_auth_status, {
|
|
@@ -9939,9 +10223,7 @@ ${"═".repeat(50)}`);
|
|
|
9939
10223
|
if (authData.deviceName) {
|
|
9940
10224
|
console.log(`\uD83D\uDCBB Device: ${authData.deviceName}`);
|
|
9941
10225
|
}
|
|
9942
|
-
|
|
9943
|
-
console.log(`\uD83D\uDCE6 CLI Version: ${authData.cliVersion}`);
|
|
9944
|
-
}
|
|
10226
|
+
console.log(`\uD83D\uDCE6 CLI Version: ${getVersion()}`);
|
|
9945
10227
|
console.log(`
|
|
9946
10228
|
⏳ Validating session...`);
|
|
9947
10229
|
try {
|
|
@@ -9955,6 +10237,28 @@ ${"═".repeat(50)}`);
|
|
|
9955
10237
|
if (validation.userName) {
|
|
9956
10238
|
console.log(`\uD83D\uDC64 User: ${validation.userName}`);
|
|
9957
10239
|
}
|
|
10240
|
+
try {
|
|
10241
|
+
const machineInfo = ensureMachineRegistered();
|
|
10242
|
+
await client2.mutation(api.machines.register, {
|
|
10243
|
+
sessionId: authData.sessionId,
|
|
10244
|
+
machineId: machineInfo.machineId,
|
|
10245
|
+
hostname: machineInfo.hostname,
|
|
10246
|
+
os: machineInfo.os,
|
|
10247
|
+
availableHarnesses: machineInfo.availableHarnesses,
|
|
10248
|
+
harnessVersions: machineInfo.harnessVersions,
|
|
10249
|
+
availableModels: []
|
|
10250
|
+
});
|
|
10251
|
+
console.log(`
|
|
10252
|
+
\uD83D\uDDA5️ Machine registered: ${machineInfo.hostname}`);
|
|
10253
|
+
console.log(` ID: ${machineInfo.machineId}`);
|
|
10254
|
+
if (machineInfo.availableHarnesses.length > 0) {
|
|
10255
|
+
console.log(` Harnesses: ${machineInfo.availableHarnesses.join(", ")}`);
|
|
10256
|
+
}
|
|
10257
|
+
} catch (machineError) {
|
|
10258
|
+
const err = machineError;
|
|
10259
|
+
console.log(`
|
|
10260
|
+
⚠️ Machine registration skipped: ${err.message}`);
|
|
10261
|
+
}
|
|
9958
10262
|
} else {
|
|
9959
10263
|
console.log(`
|
|
9960
10264
|
❌ Session is invalid: ${validation.reason}`);
|
|
@@ -9972,6 +10276,8 @@ var init_auth_status = __esm(() => {
|
|
|
9972
10276
|
init_api3();
|
|
9973
10277
|
init_storage();
|
|
9974
10278
|
init_client2();
|
|
10279
|
+
init_machine();
|
|
10280
|
+
init_version();
|
|
9975
10281
|
});
|
|
9976
10282
|
|
|
9977
10283
|
// src/commands/update.ts
|
|
@@ -10273,19 +10579,10 @@ class ProcessDriver {
|
|
|
10273
10579
|
return [];
|
|
10274
10580
|
}
|
|
10275
10581
|
}
|
|
10276
|
-
var init_process_driver = () => {};
|
|
10277
|
-
|
|
10278
|
-
// src/infrastructure/machine/types.ts
|
|
10279
|
-
var AGENT_HARNESSES, AGENT_HARNESS_COMMANDS, MACHINE_CONFIG_VERSION = "1";
|
|
10280
|
-
var init_types = __esm(() => {
|
|
10281
|
-
AGENT_HARNESSES = ["opencode"];
|
|
10282
|
-
AGENT_HARNESS_COMMANDS = {
|
|
10283
|
-
opencode: "opencode"
|
|
10284
|
-
};
|
|
10285
|
-
});
|
|
10582
|
+
var init_process_driver = () => {};
|
|
10286
10583
|
|
|
10287
10584
|
// src/infrastructure/agent-drivers/opencode-process-driver.ts
|
|
10288
|
-
import { execSync } from "node:child_process";
|
|
10585
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
10289
10586
|
var OpenCodeProcessDriver;
|
|
10290
10587
|
var init_opencode_process_driver = __esm(() => {
|
|
10291
10588
|
init_process_driver();
|
|
@@ -10318,7 +10615,7 @@ var init_opencode_process_driver = __esm(() => {
|
|
|
10318
10615
|
}
|
|
10319
10616
|
async listModels() {
|
|
10320
10617
|
try {
|
|
10321
|
-
const output =
|
|
10618
|
+
const output = execSync2("opencode models", {
|
|
10322
10619
|
stdio: ["pipe", "pipe", "pipe"],
|
|
10323
10620
|
timeout: 1e4
|
|
10324
10621
|
}).toString().trim();
|
|
@@ -10375,281 +10672,6 @@ var init_agent_drivers = __esm(() => {
|
|
|
10375
10672
|
init_opencode_process_driver();
|
|
10376
10673
|
});
|
|
10377
10674
|
|
|
10378
|
-
// src/infrastructure/machine/detection.ts
|
|
10379
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
10380
|
-
function commandExists(command) {
|
|
10381
|
-
try {
|
|
10382
|
-
const checkCommand = process.platform === "win32" ? `where ${command}` : `which ${command}`;
|
|
10383
|
-
execSync2(checkCommand, { stdio: "ignore" });
|
|
10384
|
-
return true;
|
|
10385
|
-
} catch {
|
|
10386
|
-
return false;
|
|
10387
|
-
}
|
|
10388
|
-
}
|
|
10389
|
-
function parseVersion(versionStr) {
|
|
10390
|
-
const match = versionStr.match(/v?(\d+)\.(\d+)\.(\d+)/);
|
|
10391
|
-
if (!match)
|
|
10392
|
-
return null;
|
|
10393
|
-
const major = parseInt(match[1], 10);
|
|
10394
|
-
const version2 = `${match[1]}.${match[2]}.${match[3]}`;
|
|
10395
|
-
return { version: version2, major };
|
|
10396
|
-
}
|
|
10397
|
-
function detectHarnessVersion(harness) {
|
|
10398
|
-
const versionCommand = HARNESS_VERSION_COMMANDS[harness];
|
|
10399
|
-
if (!versionCommand)
|
|
10400
|
-
return null;
|
|
10401
|
-
try {
|
|
10402
|
-
const output = execSync2(versionCommand, {
|
|
10403
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
10404
|
-
timeout: 5000
|
|
10405
|
-
}).toString().trim();
|
|
10406
|
-
return parseVersion(output);
|
|
10407
|
-
} catch {
|
|
10408
|
-
return null;
|
|
10409
|
-
}
|
|
10410
|
-
}
|
|
10411
|
-
function detectHarnessVersions(harnesses) {
|
|
10412
|
-
const versions = {};
|
|
10413
|
-
for (const harness of harnesses) {
|
|
10414
|
-
const version2 = detectHarnessVersion(harness);
|
|
10415
|
-
if (version2) {
|
|
10416
|
-
versions[harness] = version2;
|
|
10417
|
-
}
|
|
10418
|
-
}
|
|
10419
|
-
return versions;
|
|
10420
|
-
}
|
|
10421
|
-
function detectAvailableHarnesses() {
|
|
10422
|
-
const available = [];
|
|
10423
|
-
for (const harness of AGENT_HARNESSES) {
|
|
10424
|
-
const command = AGENT_HARNESS_COMMANDS[harness];
|
|
10425
|
-
if (commandExists(command)) {
|
|
10426
|
-
available.push(harness);
|
|
10427
|
-
}
|
|
10428
|
-
}
|
|
10429
|
-
return available;
|
|
10430
|
-
}
|
|
10431
|
-
var HARNESS_VERSION_COMMANDS;
|
|
10432
|
-
var init_detection = __esm(() => {
|
|
10433
|
-
init_types();
|
|
10434
|
-
HARNESS_VERSION_COMMANDS = {
|
|
10435
|
-
opencode: "opencode --version"
|
|
10436
|
-
};
|
|
10437
|
-
});
|
|
10438
|
-
|
|
10439
|
-
// src/infrastructure/machine/storage.ts
|
|
10440
|
-
import { randomUUID } from "node:crypto";
|
|
10441
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "node:fs";
|
|
10442
|
-
import { homedir as homedir2, hostname as hostname2 } from "node:os";
|
|
10443
|
-
import { join as join3 } from "node:path";
|
|
10444
|
-
function ensureConfigDir2() {
|
|
10445
|
-
if (!existsSync2(CHATROOM_DIR2)) {
|
|
10446
|
-
mkdirSync2(CHATROOM_DIR2, { recursive: true, mode: 448 });
|
|
10447
|
-
}
|
|
10448
|
-
}
|
|
10449
|
-
function getMachineConfigPath() {
|
|
10450
|
-
return join3(CHATROOM_DIR2, MACHINE_FILE);
|
|
10451
|
-
}
|
|
10452
|
-
function loadConfigFile() {
|
|
10453
|
-
const configPath = getMachineConfigPath();
|
|
10454
|
-
if (!existsSync2(configPath)) {
|
|
10455
|
-
return null;
|
|
10456
|
-
}
|
|
10457
|
-
try {
|
|
10458
|
-
const content = readFileSync3(configPath, "utf-8");
|
|
10459
|
-
return JSON.parse(content);
|
|
10460
|
-
} catch (error) {
|
|
10461
|
-
console.warn(`⚠️ Failed to read machine config at ${configPath}: ${error.message}`);
|
|
10462
|
-
console.warn(` The machine will re-register with a new identity on next startup.`);
|
|
10463
|
-
console.warn(` If this is unexpected, check the file for corruption.`);
|
|
10464
|
-
return null;
|
|
10465
|
-
}
|
|
10466
|
-
}
|
|
10467
|
-
function saveConfigFile(configFile) {
|
|
10468
|
-
ensureConfigDir2();
|
|
10469
|
-
const configPath = getMachineConfigPath();
|
|
10470
|
-
const tempPath = `${configPath}.tmp`;
|
|
10471
|
-
const content = JSON.stringify(configFile, null, 2);
|
|
10472
|
-
writeFileSync2(tempPath, content, { encoding: "utf-8", mode: 384 });
|
|
10473
|
-
renameSync(tempPath, configPath);
|
|
10474
|
-
}
|
|
10475
|
-
function loadMachineConfig() {
|
|
10476
|
-
const configFile = loadConfigFile();
|
|
10477
|
-
if (!configFile)
|
|
10478
|
-
return null;
|
|
10479
|
-
const convexUrl = getConvexUrl();
|
|
10480
|
-
return configFile.machines[convexUrl] ?? null;
|
|
10481
|
-
}
|
|
10482
|
-
function saveMachineConfig(config3) {
|
|
10483
|
-
const configFile = loadConfigFile() ?? {
|
|
10484
|
-
version: MACHINE_CONFIG_VERSION,
|
|
10485
|
-
machines: {}
|
|
10486
|
-
};
|
|
10487
|
-
const convexUrl = getConvexUrl();
|
|
10488
|
-
configFile.machines[convexUrl] = config3;
|
|
10489
|
-
saveConfigFile(configFile);
|
|
10490
|
-
}
|
|
10491
|
-
function createNewEndpointConfig() {
|
|
10492
|
-
const now = new Date().toISOString();
|
|
10493
|
-
const availableHarnesses = detectAvailableHarnesses();
|
|
10494
|
-
return {
|
|
10495
|
-
machineId: randomUUID(),
|
|
10496
|
-
hostname: hostname2(),
|
|
10497
|
-
os: process.platform,
|
|
10498
|
-
registeredAt: now,
|
|
10499
|
-
lastSyncedAt: now,
|
|
10500
|
-
availableHarnesses,
|
|
10501
|
-
harnessVersions: detectHarnessVersions(availableHarnesses),
|
|
10502
|
-
chatroomAgents: {}
|
|
10503
|
-
};
|
|
10504
|
-
}
|
|
10505
|
-
function ensureMachineRegistered() {
|
|
10506
|
-
let config3 = loadMachineConfig();
|
|
10507
|
-
if (!config3) {
|
|
10508
|
-
config3 = createNewEndpointConfig();
|
|
10509
|
-
saveMachineConfig(config3);
|
|
10510
|
-
} else {
|
|
10511
|
-
const now = new Date().toISOString();
|
|
10512
|
-
config3.availableHarnesses = detectAvailableHarnesses();
|
|
10513
|
-
config3.harnessVersions = detectHarnessVersions(config3.availableHarnesses);
|
|
10514
|
-
config3.lastSyncedAt = now;
|
|
10515
|
-
config3.hostname = hostname2();
|
|
10516
|
-
saveMachineConfig(config3);
|
|
10517
|
-
}
|
|
10518
|
-
return {
|
|
10519
|
-
machineId: config3.machineId,
|
|
10520
|
-
hostname: config3.hostname,
|
|
10521
|
-
os: config3.os,
|
|
10522
|
-
availableHarnesses: config3.availableHarnesses,
|
|
10523
|
-
harnessVersions: config3.harnessVersions
|
|
10524
|
-
};
|
|
10525
|
-
}
|
|
10526
|
-
function getMachineId() {
|
|
10527
|
-
const config3 = loadMachineConfig();
|
|
10528
|
-
return config3?.machineId ?? null;
|
|
10529
|
-
}
|
|
10530
|
-
function updateAgentContext(chatroomId, role, agentType, workingDir) {
|
|
10531
|
-
const config3 = loadMachineConfig();
|
|
10532
|
-
if (!config3) {
|
|
10533
|
-
throw new Error("Machine not registered. Run ensureMachineRegistered() first.");
|
|
10534
|
-
}
|
|
10535
|
-
const now = new Date().toISOString();
|
|
10536
|
-
if (!config3.chatroomAgents[chatroomId]) {
|
|
10537
|
-
config3.chatroomAgents[chatroomId] = {};
|
|
10538
|
-
}
|
|
10539
|
-
config3.chatroomAgents[chatroomId][role] = {
|
|
10540
|
-
agentType,
|
|
10541
|
-
workingDir,
|
|
10542
|
-
lastStartedAt: now
|
|
10543
|
-
};
|
|
10544
|
-
saveMachineConfig(config3);
|
|
10545
|
-
}
|
|
10546
|
-
function getAgentContext(chatroomId, role) {
|
|
10547
|
-
const config3 = loadMachineConfig();
|
|
10548
|
-
if (!config3) {
|
|
10549
|
-
return null;
|
|
10550
|
-
}
|
|
10551
|
-
return config3.chatroomAgents[chatroomId]?.[role] ?? null;
|
|
10552
|
-
}
|
|
10553
|
-
var CHATROOM_DIR2, MACHINE_FILE = "machine.json";
|
|
10554
|
-
var init_storage2 = __esm(() => {
|
|
10555
|
-
init_detection();
|
|
10556
|
-
init_types();
|
|
10557
|
-
init_client2();
|
|
10558
|
-
CHATROOM_DIR2 = join3(homedir2(), ".chatroom");
|
|
10559
|
-
});
|
|
10560
|
-
|
|
10561
|
-
// src/infrastructure/machine/daemon-state.ts
|
|
10562
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync2 } from "node:fs";
|
|
10563
|
-
import { homedir as homedir3 } from "node:os";
|
|
10564
|
-
import { join as join4 } from "node:path";
|
|
10565
|
-
function agentKey(chatroomId, role) {
|
|
10566
|
-
return `${chatroomId}/${role}`;
|
|
10567
|
-
}
|
|
10568
|
-
function ensureStateDir() {
|
|
10569
|
-
if (!existsSync3(STATE_DIR)) {
|
|
10570
|
-
mkdirSync3(STATE_DIR, { recursive: true, mode: 448 });
|
|
10571
|
-
}
|
|
10572
|
-
}
|
|
10573
|
-
function stateFilePath(machineId) {
|
|
10574
|
-
return join4(STATE_DIR, `${machineId}.json`);
|
|
10575
|
-
}
|
|
10576
|
-
function loadDaemonState(machineId) {
|
|
10577
|
-
const filePath = stateFilePath(machineId);
|
|
10578
|
-
if (!existsSync3(filePath)) {
|
|
10579
|
-
return null;
|
|
10580
|
-
}
|
|
10581
|
-
try {
|
|
10582
|
-
const content = readFileSync4(filePath, "utf-8");
|
|
10583
|
-
return JSON.parse(content);
|
|
10584
|
-
} catch {
|
|
10585
|
-
return null;
|
|
10586
|
-
}
|
|
10587
|
-
}
|
|
10588
|
-
function saveDaemonState(state) {
|
|
10589
|
-
ensureStateDir();
|
|
10590
|
-
const filePath = stateFilePath(state.machineId);
|
|
10591
|
-
const tempPath = `${filePath}.tmp`;
|
|
10592
|
-
const content = JSON.stringify(state, null, 2);
|
|
10593
|
-
writeFileSync3(tempPath, content, { encoding: "utf-8", mode: 384 });
|
|
10594
|
-
renameSync2(tempPath, filePath);
|
|
10595
|
-
}
|
|
10596
|
-
function loadOrCreate(machineId) {
|
|
10597
|
-
return loadDaemonState(machineId) ?? {
|
|
10598
|
-
version: STATE_VERSION,
|
|
10599
|
-
machineId,
|
|
10600
|
-
updatedAt: new Date().toISOString(),
|
|
10601
|
-
agents: {}
|
|
10602
|
-
};
|
|
10603
|
-
}
|
|
10604
|
-
function persistAgentPid(machineId, chatroomId, role, pid, harness) {
|
|
10605
|
-
const state = loadOrCreate(machineId);
|
|
10606
|
-
state.agents[agentKey(chatroomId, role)] = {
|
|
10607
|
-
pid,
|
|
10608
|
-
harness,
|
|
10609
|
-
startedAt: new Date().toISOString()
|
|
10610
|
-
};
|
|
10611
|
-
state.updatedAt = new Date().toISOString();
|
|
10612
|
-
saveDaemonState(state);
|
|
10613
|
-
}
|
|
10614
|
-
function clearAgentPid(machineId, chatroomId, role) {
|
|
10615
|
-
const state = loadDaemonState(machineId);
|
|
10616
|
-
if (!state)
|
|
10617
|
-
return;
|
|
10618
|
-
const key = agentKey(chatroomId, role);
|
|
10619
|
-
if (!(key in state.agents))
|
|
10620
|
-
return;
|
|
10621
|
-
delete state.agents[key];
|
|
10622
|
-
state.updatedAt = new Date().toISOString();
|
|
10623
|
-
saveDaemonState(state);
|
|
10624
|
-
}
|
|
10625
|
-
function listAgentEntries(machineId) {
|
|
10626
|
-
const state = loadDaemonState(machineId);
|
|
10627
|
-
if (!state)
|
|
10628
|
-
return [];
|
|
10629
|
-
const results = [];
|
|
10630
|
-
for (const [key, entry] of Object.entries(state.agents)) {
|
|
10631
|
-
const separatorIndex = key.lastIndexOf("/");
|
|
10632
|
-
if (separatorIndex === -1)
|
|
10633
|
-
continue;
|
|
10634
|
-
const chatroomId = key.substring(0, separatorIndex);
|
|
10635
|
-
const role = key.substring(separatorIndex + 1);
|
|
10636
|
-
results.push({ chatroomId, role, entry });
|
|
10637
|
-
}
|
|
10638
|
-
return results;
|
|
10639
|
-
}
|
|
10640
|
-
var CHATROOM_DIR3, STATE_DIR, STATE_VERSION = "1";
|
|
10641
|
-
var init_daemon_state = __esm(() => {
|
|
10642
|
-
CHATROOM_DIR3 = join4(homedir3(), ".chatroom");
|
|
10643
|
-
STATE_DIR = join4(CHATROOM_DIR3, "machines", "state");
|
|
10644
|
-
});
|
|
10645
|
-
|
|
10646
|
-
// src/infrastructure/machine/index.ts
|
|
10647
|
-
var init_machine = __esm(() => {
|
|
10648
|
-
init_types();
|
|
10649
|
-
init_storage2();
|
|
10650
|
-
init_daemon_state();
|
|
10651
|
-
});
|
|
10652
|
-
|
|
10653
10675
|
// src/commands/wait-for-task.ts
|
|
10654
10676
|
var exports_wait_for_task = {};
|
|
10655
10677
|
__export(exports_wait_for_task, {
|
|
@@ -12548,16 +12570,24 @@ var init_artifact = __esm(() => {
|
|
|
12548
12570
|
});
|
|
12549
12571
|
|
|
12550
12572
|
// src/commands/machine/pid.ts
|
|
12573
|
+
import { createHash } from "node:crypto";
|
|
12551
12574
|
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
12552
12575
|
import { homedir as homedir4 } from "node:os";
|
|
12553
12576
|
import { join as join5 } from "node:path";
|
|
12577
|
+
function getUrlHash() {
|
|
12578
|
+
const url = getConvexUrl();
|
|
12579
|
+
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
12580
|
+
}
|
|
12581
|
+
function getPidFileName() {
|
|
12582
|
+
return `daemon-${getUrlHash()}.pid`;
|
|
12583
|
+
}
|
|
12554
12584
|
function ensureChatroomDir() {
|
|
12555
12585
|
if (!existsSync4(CHATROOM_DIR4)) {
|
|
12556
12586
|
mkdirSync4(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
12557
12587
|
}
|
|
12558
12588
|
}
|
|
12559
12589
|
function getPidFilePath() {
|
|
12560
|
-
return join5(CHATROOM_DIR4,
|
|
12590
|
+
return join5(CHATROOM_DIR4, getPidFileName());
|
|
12561
12591
|
}
|
|
12562
12592
|
function isProcessRunning(pid) {
|
|
12563
12593
|
try {
|
|
@@ -12610,7 +12640,7 @@ function isDaemonRunning() {
|
|
|
12610
12640
|
function acquireLock() {
|
|
12611
12641
|
const { running, pid } = isDaemonRunning();
|
|
12612
12642
|
if (running) {
|
|
12613
|
-
console.error(`❌ Daemon already running (PID: ${pid})`);
|
|
12643
|
+
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
12614
12644
|
return false;
|
|
12615
12645
|
}
|
|
12616
12646
|
writePid();
|
|
@@ -12619,8 +12649,9 @@ function acquireLock() {
|
|
|
12619
12649
|
function releaseLock() {
|
|
12620
12650
|
removePid();
|
|
12621
12651
|
}
|
|
12622
|
-
var CHATROOM_DIR4
|
|
12652
|
+
var CHATROOM_DIR4;
|
|
12623
12653
|
var init_pid = __esm(() => {
|
|
12654
|
+
init_client2();
|
|
12624
12655
|
CHATROOM_DIR4 = join5(homedir4(), ".chatroom");
|
|
12625
12656
|
});
|
|
12626
12657
|
|