0agent 1.0.91 → 1.0.93
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/bin/0agent.js +1 -1
- package/dist/daemon.mjs +262 -149
- package/package.json +1 -1
package/bin/0agent.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, openSync } from 'node:fs';
|
|
23
23
|
import { resolve, dirname } from 'node:path';
|
|
24
|
-
import { homedir, platform } from 'node:os';
|
|
24
|
+
import { homedir, platform, arch } from 'node:os';
|
|
25
25
|
import { spawn, execSync } from 'node:child_process';
|
|
26
26
|
import { createInterface } from 'node:readline';
|
|
27
27
|
|
package/dist/daemon.mjs
CHANGED
|
@@ -1507,7 +1507,7 @@ var init_EdgeWeightUpdater = __esm({
|
|
|
1507
1507
|
this.weightLog.append(event);
|
|
1508
1508
|
}
|
|
1509
1509
|
sleep(ms) {
|
|
1510
|
-
return new Promise((
|
|
1510
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
1511
1511
|
}
|
|
1512
1512
|
};
|
|
1513
1513
|
}
|
|
@@ -4170,7 +4170,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4170
4170
|
}
|
|
4171
4171
|
/** Async pip install — never blocks the event loop (unlike spawnSync). */
|
|
4172
4172
|
_pipInstall(pkg, signal) {
|
|
4173
|
-
return new Promise((
|
|
4173
|
+
return new Promise((resolve20) => {
|
|
4174
4174
|
const proc = spawn4("pip3", ["install", pkg, "-q"], {
|
|
4175
4175
|
env: process.env,
|
|
4176
4176
|
stdio: "ignore"
|
|
@@ -4181,7 +4181,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4181
4181
|
settled = true;
|
|
4182
4182
|
signal?.removeEventListener("abort", onAbort);
|
|
4183
4183
|
clearTimeout(timer);
|
|
4184
|
-
|
|
4184
|
+
resolve20(ok);
|
|
4185
4185
|
};
|
|
4186
4186
|
const onAbort = () => {
|
|
4187
4187
|
try {
|
|
@@ -4203,7 +4203,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4203
4203
|
});
|
|
4204
4204
|
}
|
|
4205
4205
|
_runScript(scriptPath, stdinData, signal) {
|
|
4206
|
-
return new Promise((
|
|
4206
|
+
return new Promise((resolve20) => {
|
|
4207
4207
|
const proc = spawn4("python3", [scriptPath], {
|
|
4208
4208
|
env: process.env,
|
|
4209
4209
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4216,7 +4216,7 @@ Run manually: pip3 install open-interpreter`,
|
|
|
4216
4216
|
settled = true;
|
|
4217
4217
|
signal?.removeEventListener("abort", onAbort);
|
|
4218
4218
|
clearTimeout(timer);
|
|
4219
|
-
|
|
4219
|
+
resolve20({ stdout: out.join(""), stderr: err.join(""), code });
|
|
4220
4220
|
};
|
|
4221
4221
|
const onAbort = () => {
|
|
4222
4222
|
try {
|
|
@@ -6203,7 +6203,7 @@ var init_AgentExecutor = __esm({
|
|
|
6203
6203
|
}
|
|
6204
6204
|
// ─── Legacy tool execution (used by built-in tools, not capabilities) ──────
|
|
6205
6205
|
shellExec(command, timeoutMs) {
|
|
6206
|
-
return new Promise((
|
|
6206
|
+
return new Promise((resolve20) => {
|
|
6207
6207
|
const chunks = [];
|
|
6208
6208
|
const proc = spawn5("bash", ["-c", command], {
|
|
6209
6209
|
cwd: this.cwd,
|
|
@@ -6214,10 +6214,10 @@ var init_AgentExecutor = __esm({
|
|
|
6214
6214
|
proc.stderr.on("data", (d) => chunks.push(d.toString()));
|
|
6215
6215
|
proc.on("close", (code) => {
|
|
6216
6216
|
const output = chunks.join("").trim();
|
|
6217
|
-
|
|
6217
|
+
resolve20(output || (code === 0 ? "(command completed, no output)" : `exit code ${code}`));
|
|
6218
6218
|
});
|
|
6219
6219
|
proc.on("error", (err) => {
|
|
6220
|
-
|
|
6220
|
+
resolve20(`Error: ${err.message}`);
|
|
6221
6221
|
});
|
|
6222
6222
|
});
|
|
6223
6223
|
}
|
|
@@ -6733,8 +6733,8 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
6733
6733
|
});
|
|
6734
6734
|
|
|
6735
6735
|
// packages/daemon/src/ExecutionVerifier.ts
|
|
6736
|
-
import { existsSync as
|
|
6737
|
-
import { resolve as
|
|
6736
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
6737
|
+
import { resolve as resolve9 } from "node:path";
|
|
6738
6738
|
var ExecutionVerifier;
|
|
6739
6739
|
var init_ExecutionVerifier = __esm({
|
|
6740
6740
|
"packages/daemon/src/ExecutionVerifier.ts"() {
|
|
@@ -6771,8 +6771,8 @@ var init_ExecutionVerifier = __esm({
|
|
|
6771
6771
|
};
|
|
6772
6772
|
}
|
|
6773
6773
|
if (files.length > 0) {
|
|
6774
|
-
const lastFile =
|
|
6775
|
-
const exists =
|
|
6774
|
+
const lastFile = resolve9(this.cwd, files[files.length - 1]);
|
|
6775
|
+
const exists = existsSync10(lastFile);
|
|
6776
6776
|
return {
|
|
6777
6777
|
success: exists,
|
|
6778
6778
|
method: "file_exists",
|
|
@@ -6811,8 +6811,8 @@ var init_ExecutionVerifier = __esm({
|
|
|
6811
6811
|
});
|
|
6812
6812
|
|
|
6813
6813
|
// packages/daemon/src/RuntimeSelfHeal.ts
|
|
6814
|
-
import { readFileSync as
|
|
6815
|
-
import { resolve as
|
|
6814
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync11 } from "node:fs";
|
|
6815
|
+
import { resolve as resolve10, dirname as dirname3 } from "node:path";
|
|
6816
6816
|
import { fileURLToPath } from "node:url";
|
|
6817
6817
|
import { execSync as execSync7, spawn as spawn6 } from "node:child_process";
|
|
6818
6818
|
function isRuntimeBug(error) {
|
|
@@ -6838,8 +6838,8 @@ function parseStackTrace(stack) {
|
|
|
6838
6838
|
}
|
|
6839
6839
|
function extractContext(filePath, errorLine, contextLines = 30) {
|
|
6840
6840
|
try {
|
|
6841
|
-
if (!
|
|
6842
|
-
const content =
|
|
6841
|
+
if (!existsSync11(filePath)) return null;
|
|
6842
|
+
const content = readFileSync8(filePath, "utf8");
|
|
6843
6843
|
const lines = content.split("\n");
|
|
6844
6844
|
const start = Math.max(0, errorLine - contextLines);
|
|
6845
6845
|
const end = Math.min(lines.length, errorLine + contextLines);
|
|
@@ -6884,8 +6884,8 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6884
6884
|
this.llm = llm;
|
|
6885
6885
|
this.eventBus = eventBus;
|
|
6886
6886
|
let dir = dirname3(fileURLToPath(import.meta.url));
|
|
6887
|
-
while (dir !== "/" && !
|
|
6888
|
-
dir =
|
|
6887
|
+
while (dir !== "/" && !existsSync11(resolve10(dir, "package.json"))) {
|
|
6888
|
+
dir = resolve10(dir, "..");
|
|
6889
6889
|
}
|
|
6890
6890
|
this.projectRoot = dir;
|
|
6891
6891
|
}
|
|
@@ -6921,7 +6921,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6921
6921
|
*/
|
|
6922
6922
|
async applyPatch(proposal) {
|
|
6923
6923
|
const tsPath = this.findSourceFile(proposal.location);
|
|
6924
|
-
if (!tsPath || !
|
|
6924
|
+
if (!tsPath || !existsSync11(tsPath)) {
|
|
6925
6925
|
return {
|
|
6926
6926
|
applied: false,
|
|
6927
6927
|
restarted: false,
|
|
@@ -6929,9 +6929,9 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6929
6929
|
};
|
|
6930
6930
|
}
|
|
6931
6931
|
try {
|
|
6932
|
-
const original =
|
|
6932
|
+
const original = readFileSync8(tsPath, "utf8");
|
|
6933
6933
|
const backup = tsPath + ".bak";
|
|
6934
|
-
|
|
6934
|
+
writeFileSync6(backup, original, "utf8");
|
|
6935
6935
|
if (!original.includes(proposal.original_code.trim())) {
|
|
6936
6936
|
return {
|
|
6937
6937
|
applied: false,
|
|
@@ -6940,9 +6940,9 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6940
6940
|
};
|
|
6941
6941
|
}
|
|
6942
6942
|
const patched = original.replace(proposal.original_code, proposal.proposed_code);
|
|
6943
|
-
|
|
6944
|
-
const bundleScript =
|
|
6945
|
-
if (
|
|
6943
|
+
writeFileSync6(tsPath, patched, "utf8");
|
|
6944
|
+
const bundleScript = resolve10(this.projectRoot, "scripts", "bundle.mjs");
|
|
6945
|
+
if (existsSync11(bundleScript)) {
|
|
6946
6946
|
try {
|
|
6947
6947
|
execSync7(`node "${bundleScript}"`, {
|
|
6948
6948
|
cwd: this.projectRoot,
|
|
@@ -6950,7 +6950,7 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6950
6950
|
stdio: "ignore"
|
|
6951
6951
|
});
|
|
6952
6952
|
} catch {
|
|
6953
|
-
|
|
6953
|
+
writeFileSync6(tsPath, original, "utf8");
|
|
6954
6954
|
return {
|
|
6955
6955
|
applied: false,
|
|
6956
6956
|
restarted: false,
|
|
@@ -6975,14 +6975,14 @@ var init_RuntimeSelfHeal = __esm({
|
|
|
6975
6975
|
// ─── Private helpers ───────────────────────────────────────────────────────
|
|
6976
6976
|
findSourceFile(location) {
|
|
6977
6977
|
const candidates = [
|
|
6978
|
-
|
|
6978
|
+
resolve10(this.projectRoot, location.relPath),
|
|
6979
6979
|
// If relPath starts with dist/, look in src/
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6980
|
+
resolve10(this.projectRoot, location.relPath.replace(/^dist\//, "src/").replace(/\.js$/, ".ts")),
|
|
6981
|
+
resolve10(this.projectRoot, "packages", "daemon", "src", location.relPath.replace(/.*src\//, "")),
|
|
6982
|
+
resolve10(this.projectRoot, "packages", "core", "src", location.relPath.replace(/.*src\//, ""))
|
|
6983
6983
|
];
|
|
6984
6984
|
for (const p of candidates) {
|
|
6985
|
-
if (
|
|
6985
|
+
if (existsSync11(p)) return p;
|
|
6986
6986
|
}
|
|
6987
6987
|
return null;
|
|
6988
6988
|
}
|
|
@@ -7047,8 +7047,8 @@ Rules:
|
|
|
7047
7047
|
}
|
|
7048
7048
|
}
|
|
7049
7049
|
restartDaemon() {
|
|
7050
|
-
const bundlePath =
|
|
7051
|
-
if (
|
|
7050
|
+
const bundlePath = resolve10(this.projectRoot, "dist", "daemon.mjs");
|
|
7051
|
+
if (existsSync11(bundlePath)) {
|
|
7052
7052
|
const child = spawn6(process.execPath, [bundlePath], {
|
|
7053
7053
|
detached: true,
|
|
7054
7054
|
stdio: "ignore",
|
|
@@ -7153,8 +7153,8 @@ __export(ProactiveSurface_exports, {
|
|
|
7153
7153
|
ProactiveSurface: () => ProactiveSurface
|
|
7154
7154
|
});
|
|
7155
7155
|
import { execSync as execSync10 } from "node:child_process";
|
|
7156
|
-
import { existsSync as
|
|
7157
|
-
import { resolve as
|
|
7156
|
+
import { existsSync as existsSync21, readFileSync as readFileSync17, statSync as statSync3, readdirSync as readdirSync5 } from "node:fs";
|
|
7157
|
+
import { resolve as resolve17, join as join7 } from "node:path";
|
|
7158
7158
|
function readdirSafe(dir) {
|
|
7159
7159
|
try {
|
|
7160
7160
|
return readdirSync5(dir);
|
|
@@ -7203,7 +7203,7 @@ var init_ProactiveSurface = __esm({
|
|
|
7203
7203
|
return [...this.insights];
|
|
7204
7204
|
}
|
|
7205
7205
|
async poll() {
|
|
7206
|
-
if (!
|
|
7206
|
+
if (!existsSync21(resolve17(this.cwd, ".git"))) return;
|
|
7207
7207
|
const newInsights = [];
|
|
7208
7208
|
const gitInsight = this.checkGitActivity();
|
|
7209
7209
|
if (gitInsight) newInsights.push(gitInsight);
|
|
@@ -7247,13 +7247,13 @@ var init_ProactiveSurface = __esm({
|
|
|
7247
7247
|
];
|
|
7248
7248
|
for (const dir of outputPaths) {
|
|
7249
7249
|
try {
|
|
7250
|
-
if (!
|
|
7250
|
+
if (!existsSync21(dir)) continue;
|
|
7251
7251
|
const xmlFiles = readdirSafe(dir).filter((f) => f.endsWith(".xml"));
|
|
7252
7252
|
for (const xml of xmlFiles) {
|
|
7253
7253
|
const path = join7(dir, xml);
|
|
7254
7254
|
const stat = statSync3(path);
|
|
7255
7255
|
if (stat.mtimeMs < this.lastPollAt) continue;
|
|
7256
|
-
const content =
|
|
7256
|
+
const content = readFileSync17(path, "utf8");
|
|
7257
7257
|
const failures = [...content.matchAll(/<failure[^>]*message="([^"]+)"/g)].length;
|
|
7258
7258
|
if (failures > 0) {
|
|
7259
7259
|
return this.makeInsight(
|
|
@@ -7308,9 +7308,9 @@ var init_ProactiveSurface = __esm({
|
|
|
7308
7308
|
|
|
7309
7309
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
7310
7310
|
init_src();
|
|
7311
|
-
import { writeFileSync as
|
|
7312
|
-
import { resolve as
|
|
7313
|
-
import { homedir as
|
|
7311
|
+
import { writeFileSync as writeFileSync13, unlinkSync as unlinkSync4, existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync18 } from "node:fs";
|
|
7312
|
+
import { resolve as resolve18 } from "node:path";
|
|
7313
|
+
import { homedir as homedir10 } from "node:os";
|
|
7314
7314
|
|
|
7315
7315
|
// packages/daemon/src/config/DaemonConfig.ts
|
|
7316
7316
|
import { readFileSync, existsSync } from "node:fs";
|
|
@@ -7811,19 +7811,19 @@ var ProjectScanner = class {
|
|
|
7811
7811
|
async getRunningPorts() {
|
|
7812
7812
|
const open = [];
|
|
7813
7813
|
await Promise.all(PORTS_TO_CHECK.map(
|
|
7814
|
-
(port) => new Promise((
|
|
7814
|
+
(port) => new Promise((resolve20) => {
|
|
7815
7815
|
const s = createServer();
|
|
7816
7816
|
s.listen(port, "127.0.0.1", () => {
|
|
7817
7817
|
s.close();
|
|
7818
|
-
|
|
7818
|
+
resolve20();
|
|
7819
7819
|
});
|
|
7820
7820
|
s.on("error", () => {
|
|
7821
7821
|
open.push(port);
|
|
7822
|
-
|
|
7822
|
+
resolve20();
|
|
7823
7823
|
});
|
|
7824
7824
|
setTimeout(() => {
|
|
7825
7825
|
s.close();
|
|
7826
|
-
|
|
7826
|
+
resolve20();
|
|
7827
7827
|
}, 200);
|
|
7828
7828
|
})
|
|
7829
7829
|
));
|
|
@@ -8088,10 +8088,119 @@ var AutoMemoryExtractor = class {
|
|
|
8088
8088
|
}
|
|
8089
8089
|
};
|
|
8090
8090
|
|
|
8091
|
-
// packages/daemon/src/
|
|
8092
|
-
import { readFileSync as
|
|
8093
|
-
import { resolve as
|
|
8091
|
+
// packages/daemon/src/services/MemoryHeartbeat.ts
|
|
8092
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync5, appendFileSync, mkdirSync as mkdirSync4 } from "node:fs";
|
|
8093
|
+
import { resolve as resolve8 } from "node:path";
|
|
8094
8094
|
import { homedir as homedir3 } from "node:os";
|
|
8095
|
+
var AGENT_DIR = resolve8(homedir3(), ".0agent");
|
|
8096
|
+
var MEMORY_PATH = resolve8(AGENT_DIR, "MEMORY.md");
|
|
8097
|
+
var IDENTITY_PATH = resolve8(AGENT_DIR, "identity.md");
|
|
8098
|
+
var SOUL_PATH = resolve8(AGENT_DIR, "soul.md");
|
|
8099
|
+
var MemoryHeartbeat = class {
|
|
8100
|
+
constructor(llm) {
|
|
8101
|
+
this.llm = llm;
|
|
8102
|
+
mkdirSync4(AGENT_DIR, { recursive: true });
|
|
8103
|
+
}
|
|
8104
|
+
hourlyTimer = null;
|
|
8105
|
+
sessionCount = 0;
|
|
8106
|
+
/** Start the hourly consolidation timer. */
|
|
8107
|
+
start() {
|
|
8108
|
+
if (this.hourlyTimer) return;
|
|
8109
|
+
this.hourlyTimer = setInterval(() => this._hourlyConsolidate().catch(() => {
|
|
8110
|
+
}), 60 * 60 * 1e3);
|
|
8111
|
+
}
|
|
8112
|
+
stop() {
|
|
8113
|
+
if (this.hourlyTimer) {
|
|
8114
|
+
clearInterval(this.hourlyTimer);
|
|
8115
|
+
this.hourlyTimer = null;
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
/**
|
|
8119
|
+
* Called after every completed session. Appends a one-liner to MEMORY.md.
|
|
8120
|
+
* Fast, synchronous, never blocks.
|
|
8121
|
+
*/
|
|
8122
|
+
afterSession(task, output, model) {
|
|
8123
|
+
this.sessionCount++;
|
|
8124
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
8125
|
+
const taskSummary = task.slice(0, 100).replace(/\n/g, " ");
|
|
8126
|
+
const outputSummary = output.slice(0, 100).replace(/\n/g, " ");
|
|
8127
|
+
if (!existsSync9(MEMORY_PATH)) {
|
|
8128
|
+
writeFileSync5(MEMORY_PATH, "# Memory\n\nSession log \u2014 auto-updated after every interaction.\n\n", "utf8");
|
|
8129
|
+
}
|
|
8130
|
+
const line = `- [${timestamp}] **${taskSummary}** \u2192 ${outputSummary}${output.length > 100 ? "\u2026" : ""}
|
|
8131
|
+
`;
|
|
8132
|
+
try {
|
|
8133
|
+
appendFileSync(MEMORY_PATH, line, "utf8");
|
|
8134
|
+
} catch {
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
8137
|
+
/**
|
|
8138
|
+
* Hourly consolidation: reviews MEMORY.md and updates identity.md and soul.md
|
|
8139
|
+
* with anything learned. Uses LLM to synthesize.
|
|
8140
|
+
*/
|
|
8141
|
+
async _hourlyConsolidate() {
|
|
8142
|
+
if (!this.llm?.isConfigured) return;
|
|
8143
|
+
if (this.sessionCount === 0) return;
|
|
8144
|
+
const memoryContent = this._readFile(MEMORY_PATH);
|
|
8145
|
+
const identityContent = this._readFile(IDENTITY_PATH);
|
|
8146
|
+
const soulContent = this._readFile(SOUL_PATH);
|
|
8147
|
+
if (!memoryContent) return;
|
|
8148
|
+
const prompt = [
|
|
8149
|
+
"You manage three files for a persistent AI agent. Review the recent memory log",
|
|
8150
|
+
"and determine if identity.md or soul.md need updates.",
|
|
8151
|
+
"",
|
|
8152
|
+
"## Current MEMORY.md (session log):",
|
|
8153
|
+
memoryContent.slice(-3e3),
|
|
8154
|
+
"",
|
|
8155
|
+
"## Current identity.md:",
|
|
8156
|
+
identityContent?.slice(0, 1500) || "(empty)",
|
|
8157
|
+
"",
|
|
8158
|
+
"## Current soul.md:",
|
|
8159
|
+
soulContent?.slice(0, 1500) || "(empty)",
|
|
8160
|
+
"",
|
|
8161
|
+
"## Instructions:",
|
|
8162
|
+
"Return a JSON object with two optional fields:",
|
|
8163
|
+
`- "identity_append": text to APPEND to identity.md (new facts about the owner, new capabilities, new projects). Only include if there's something new.`,
|
|
8164
|
+
`- "soul_append": text to APPEND to soul.md (learned preferences, communication style insights, new boundaries). Only include if there's something new.`,
|
|
8165
|
+
"",
|
|
8166
|
+
"Return {} if nothing needs updating.",
|
|
8167
|
+
"Keep additions concise \u2014 1-3 lines max per field."
|
|
8168
|
+
].join("\n");
|
|
8169
|
+
try {
|
|
8170
|
+
const resp = await this.llm.complete(
|
|
8171
|
+
[{ role: "user", content: prompt }],
|
|
8172
|
+
"You are a memory manager. Return ONLY valid JSON. No explanation."
|
|
8173
|
+
);
|
|
8174
|
+
const jsonMatch = resp.content.match(/\{[\s\S]*\}/);
|
|
8175
|
+
if (!jsonMatch) return;
|
|
8176
|
+
const updates = JSON.parse(jsonMatch[0]);
|
|
8177
|
+
if (updates.identity_append?.trim()) {
|
|
8178
|
+
appendFileSync(IDENTITY_PATH, `
|
|
8179
|
+
${updates.identity_append.trim()}
|
|
8180
|
+
`, "utf8");
|
|
8181
|
+
}
|
|
8182
|
+
if (updates.soul_append?.trim()) {
|
|
8183
|
+
appendFileSync(SOUL_PATH, `
|
|
8184
|
+
${updates.soul_append.trim()}
|
|
8185
|
+
`, "utf8");
|
|
8186
|
+
}
|
|
8187
|
+
this.sessionCount = 0;
|
|
8188
|
+
} catch {
|
|
8189
|
+
}
|
|
8190
|
+
}
|
|
8191
|
+
_readFile(path) {
|
|
8192
|
+
try {
|
|
8193
|
+
return existsSync9(path) ? readFileSync7(path, "utf8") : null;
|
|
8194
|
+
} catch {
|
|
8195
|
+
return null;
|
|
8196
|
+
}
|
|
8197
|
+
}
|
|
8198
|
+
};
|
|
8199
|
+
|
|
8200
|
+
// packages/daemon/src/SessionManager.ts
|
|
8201
|
+
import { readFileSync as readFileSync9, existsSync as existsSync12 } from "node:fs";
|
|
8202
|
+
import { resolve as resolve11 } from "node:path";
|
|
8203
|
+
import { homedir as homedir4 } from "node:os";
|
|
8095
8204
|
import YAML2 from "yaml";
|
|
8096
8205
|
var SessionManager = class {
|
|
8097
8206
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -8108,6 +8217,7 @@ var SessionManager = class {
|
|
|
8108
8217
|
anthropicFetcher = new AnthropicSkillFetcher();
|
|
8109
8218
|
agentRoot;
|
|
8110
8219
|
onMemoryWritten;
|
|
8220
|
+
heartbeat = new MemoryHeartbeat();
|
|
8111
8221
|
constructor(deps = {}) {
|
|
8112
8222
|
this.inferenceEngine = deps.inferenceEngine;
|
|
8113
8223
|
this.eventBus = deps.eventBus;
|
|
@@ -8118,6 +8228,8 @@ var SessionManager = class {
|
|
|
8118
8228
|
this.projectContext = deps.projectContext;
|
|
8119
8229
|
this.agentRoot = deps.agentRoot;
|
|
8120
8230
|
this.onMemoryWritten = deps.onMemoryWritten;
|
|
8231
|
+
this.heartbeat = new MemoryHeartbeat(deps.llm);
|
|
8232
|
+
this.heartbeat.start();
|
|
8121
8233
|
if (deps.adapter) {
|
|
8122
8234
|
this.conversationStore = new ConversationStore(deps.adapter);
|
|
8123
8235
|
this.conversationStore.init();
|
|
@@ -8487,8 +8599,9 @@ Current task:`;
|
|
|
8487
8599
|
tokens_used: agentResult.tokens_used,
|
|
8488
8600
|
model: agentResult.model
|
|
8489
8601
|
});
|
|
8602
|
+
this.heartbeat.afterSession(enrichedReq.task, agentResult.output, agentResult.model);
|
|
8490
8603
|
} else {
|
|
8491
|
-
const cfgPath =
|
|
8604
|
+
const cfgPath = resolve11(homedir4(), ".0agent", "config.yaml");
|
|
8492
8605
|
const output = `No LLM API key found. Add one to ${cfgPath} or run: 0agent init`;
|
|
8493
8606
|
this.addStep(sessionId, "\u26A0 No LLM API key configured \u2014 run: 0agent init");
|
|
8494
8607
|
this.completeSession(sessionId, { output });
|
|
@@ -8531,9 +8644,9 @@ Current task:`;
|
|
|
8531
8644
|
*/
|
|
8532
8645
|
getFreshLLM() {
|
|
8533
8646
|
try {
|
|
8534
|
-
const configPath =
|
|
8535
|
-
if (!
|
|
8536
|
-
const raw =
|
|
8647
|
+
const configPath = resolve11(homedir4(), ".0agent", "config.yaml");
|
|
8648
|
+
if (!existsSync12(configPath)) return this.llm;
|
|
8649
|
+
const raw = readFileSync9(configPath, "utf8");
|
|
8537
8650
|
const cfg = YAML2.parse(raw);
|
|
8538
8651
|
const providers = cfg.llm_providers;
|
|
8539
8652
|
if (!providers?.length) return this.llm;
|
|
@@ -8559,9 +8672,9 @@ Current task:`;
|
|
|
8559
8672
|
if (!this.graph) return;
|
|
8560
8673
|
let extractLLM;
|
|
8561
8674
|
try {
|
|
8562
|
-
const cfgPath =
|
|
8563
|
-
if (
|
|
8564
|
-
const raw =
|
|
8675
|
+
const cfgPath = resolve11(homedir4(), ".0agent", "config.yaml");
|
|
8676
|
+
if (existsSync12(cfgPath)) {
|
|
8677
|
+
const raw = readFileSync9(cfgPath, "utf8");
|
|
8565
8678
|
const cfg = YAML2.parse(raw);
|
|
8566
8679
|
const prov = cfg.llm_providers?.find((p) => p.is_default) ?? cfg.llm_providers?.[0];
|
|
8567
8680
|
if (prov?.api_key && prov.provider === "anthropic") {
|
|
@@ -8924,9 +9037,9 @@ var BackgroundWorkers = class {
|
|
|
8924
9037
|
};
|
|
8925
9038
|
|
|
8926
9039
|
// packages/daemon/src/skills/SkillRegistry.ts
|
|
8927
|
-
import { readFileSync as
|
|
9040
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync13, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync5 } from "node:fs";
|
|
8928
9041
|
import { join as join3 } from "node:path";
|
|
8929
|
-
import { homedir as
|
|
9042
|
+
import { homedir as homedir5 } from "node:os";
|
|
8930
9043
|
import YAML3 from "yaml";
|
|
8931
9044
|
var SkillRegistry = class {
|
|
8932
9045
|
skills = /* @__PURE__ */ new Map();
|
|
@@ -8934,8 +9047,8 @@ var SkillRegistry = class {
|
|
|
8934
9047
|
builtinDir;
|
|
8935
9048
|
customDir;
|
|
8936
9049
|
constructor(opts) {
|
|
8937
|
-
this.builtinDir = opts?.builtinDir ?? join3(
|
|
8938
|
-
this.customDir = opts?.customDir ?? join3(
|
|
9050
|
+
this.builtinDir = opts?.builtinDir ?? join3(homedir5(), ".0agent", "skills", "builtin");
|
|
9051
|
+
this.customDir = opts?.customDir ?? join3(homedir5(), ".0agent", "skills", "custom");
|
|
8939
9052
|
}
|
|
8940
9053
|
/**
|
|
8941
9054
|
* Load all skills from builtin + custom directories.
|
|
@@ -8947,11 +9060,11 @@ var SkillRegistry = class {
|
|
|
8947
9060
|
this.loadFromDir(this.customDir, false);
|
|
8948
9061
|
}
|
|
8949
9062
|
loadFromDir(dir, isBuiltin) {
|
|
8950
|
-
if (!
|
|
9063
|
+
if (!existsSync13(dir)) return;
|
|
8951
9064
|
const files = readdirSync3(dir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
8952
9065
|
for (const file of files) {
|
|
8953
9066
|
try {
|
|
8954
|
-
const raw =
|
|
9067
|
+
const raw = readFileSync10(join3(dir, file), "utf8");
|
|
8955
9068
|
const skill = YAML3.parse(raw);
|
|
8956
9069
|
if (skill.name) {
|
|
8957
9070
|
this.skills.set(skill.name, skill);
|
|
@@ -8986,9 +9099,9 @@ var SkillRegistry = class {
|
|
|
8986
9099
|
if (this.builtinNames.has(name)) {
|
|
8987
9100
|
throw new Error(`Cannot override built-in skill: ${name}`);
|
|
8988
9101
|
}
|
|
8989
|
-
|
|
9102
|
+
mkdirSync5(this.customDir, { recursive: true });
|
|
8990
9103
|
const filePath = join3(this.customDir, `${name}.yaml`);
|
|
8991
|
-
|
|
9104
|
+
writeFileSync7(filePath, yamlContent, "utf8");
|
|
8992
9105
|
const skill = YAML3.parse(yamlContent);
|
|
8993
9106
|
this.skills.set(name, skill);
|
|
8994
9107
|
return skill;
|
|
@@ -9001,7 +9114,7 @@ var SkillRegistry = class {
|
|
|
9001
9114
|
throw new Error(`Cannot delete built-in skill: ${name}`);
|
|
9002
9115
|
}
|
|
9003
9116
|
const filePath = join3(this.customDir, `${name}.yaml`);
|
|
9004
|
-
if (
|
|
9117
|
+
if (existsSync13(filePath)) {
|
|
9005
9118
|
unlinkSync3(filePath);
|
|
9006
9119
|
}
|
|
9007
9120
|
this.skills.delete(name);
|
|
@@ -9014,8 +9127,8 @@ var SkillRegistry = class {
|
|
|
9014
9127
|
// packages/daemon/src/HTTPServer.ts
|
|
9015
9128
|
import { Hono as Hono14 } from "hono";
|
|
9016
9129
|
import { serve } from "@hono/node-server";
|
|
9017
|
-
import { readFileSync as
|
|
9018
|
-
import { resolve as
|
|
9130
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
9131
|
+
import { resolve as resolve13, dirname as dirname4 } from "node:path";
|
|
9019
9132
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
9020
9133
|
|
|
9021
9134
|
// packages/daemon/src/routes/health.ts
|
|
@@ -9307,20 +9420,20 @@ function memoryRoutes(deps) {
|
|
|
9307
9420
|
// packages/daemon/src/routes/llm.ts
|
|
9308
9421
|
init_LLMExecutor();
|
|
9309
9422
|
import { Hono as Hono10 } from "hono";
|
|
9310
|
-
import { readFileSync as
|
|
9311
|
-
import { resolve as
|
|
9312
|
-
import { homedir as
|
|
9423
|
+
import { readFileSync as readFileSync11, existsSync as existsSync14 } from "node:fs";
|
|
9424
|
+
import { resolve as resolve12 } from "node:path";
|
|
9425
|
+
import { homedir as homedir6 } from "node:os";
|
|
9313
9426
|
import YAML4 from "yaml";
|
|
9314
9427
|
function llmRoutes() {
|
|
9315
9428
|
const app = new Hono10();
|
|
9316
9429
|
app.post("/ping", async (c) => {
|
|
9317
9430
|
const start = Date.now();
|
|
9318
9431
|
try {
|
|
9319
|
-
const configPath =
|
|
9320
|
-
if (!
|
|
9432
|
+
const configPath = resolve12(homedir6(), ".0agent", "config.yaml");
|
|
9433
|
+
if (!existsSync14(configPath)) {
|
|
9321
9434
|
return c.json({ ok: false, error: "Config not found. Run: 0agent init" });
|
|
9322
9435
|
}
|
|
9323
|
-
const cfg = YAML4.parse(
|
|
9436
|
+
const cfg = YAML4.parse(readFileSync11(configPath, "utf8"));
|
|
9324
9437
|
const providers = cfg.llm_providers;
|
|
9325
9438
|
const def = providers?.find((p) => p.is_default) ?? providers?.[0];
|
|
9326
9439
|
if (!def) {
|
|
@@ -9835,15 +9948,15 @@ function runtimeRoutes(deps) {
|
|
|
9835
9948
|
// packages/daemon/src/HTTPServer.ts
|
|
9836
9949
|
function findGraphHtml() {
|
|
9837
9950
|
const candidates = [
|
|
9838
|
-
|
|
9951
|
+
resolve13(dirname4(fileURLToPath2(import.meta.url)), "graph.html"),
|
|
9839
9952
|
// dev (src/)
|
|
9840
|
-
|
|
9953
|
+
resolve13(dirname4(fileURLToPath2(import.meta.url)), "..", "graph.html"),
|
|
9841
9954
|
// bundled (dist/../)
|
|
9842
|
-
|
|
9955
|
+
resolve13(dirname4(fileURLToPath2(import.meta.url)), "..", "dist", "graph.html")
|
|
9843
9956
|
];
|
|
9844
9957
|
for (const p of candidates) {
|
|
9845
9958
|
try {
|
|
9846
|
-
|
|
9959
|
+
readFileSync12(p);
|
|
9847
9960
|
return p;
|
|
9848
9961
|
} catch {
|
|
9849
9962
|
}
|
|
@@ -9879,7 +9992,7 @@ var HTTPServer = class {
|
|
|
9879
9992
|
}
|
|
9880
9993
|
const serveGraph = (c) => {
|
|
9881
9994
|
try {
|
|
9882
|
-
const html =
|
|
9995
|
+
const html = readFileSync12(GRAPH_HTML_PATH, "utf8");
|
|
9883
9996
|
return c.html(html);
|
|
9884
9997
|
} catch {
|
|
9885
9998
|
return c.html("<p>Graph UI not found. Run: pnpm build</p>");
|
|
@@ -9889,7 +10002,7 @@ var HTTPServer = class {
|
|
|
9889
10002
|
this.app.get("/graph", serveGraph);
|
|
9890
10003
|
}
|
|
9891
10004
|
start() {
|
|
9892
|
-
return new Promise((
|
|
10005
|
+
return new Promise((resolve20) => {
|
|
9893
10006
|
this.server = serve(
|
|
9894
10007
|
{
|
|
9895
10008
|
fetch: this.app.fetch,
|
|
@@ -9897,20 +10010,20 @@ var HTTPServer = class {
|
|
|
9897
10010
|
hostname: this.deps.host
|
|
9898
10011
|
},
|
|
9899
10012
|
() => {
|
|
9900
|
-
|
|
10013
|
+
resolve20();
|
|
9901
10014
|
}
|
|
9902
10015
|
);
|
|
9903
10016
|
});
|
|
9904
10017
|
}
|
|
9905
10018
|
stop() {
|
|
9906
|
-
return new Promise((
|
|
10019
|
+
return new Promise((resolve20, reject) => {
|
|
9907
10020
|
if (!this.server) {
|
|
9908
|
-
|
|
10021
|
+
resolve20();
|
|
9909
10022
|
return;
|
|
9910
10023
|
}
|
|
9911
10024
|
this.server.close((err) => {
|
|
9912
10025
|
if (err) reject(err);
|
|
9913
|
-
else
|
|
10026
|
+
else resolve20();
|
|
9914
10027
|
});
|
|
9915
10028
|
});
|
|
9916
10029
|
}
|
|
@@ -9924,11 +10037,11 @@ init_LLMExecutor();
|
|
|
9924
10037
|
|
|
9925
10038
|
// packages/daemon/src/utils/IdentityManager.ts
|
|
9926
10039
|
init_src();
|
|
9927
|
-
import { readFileSync as
|
|
9928
|
-
import { resolve as
|
|
9929
|
-
import { homedir as
|
|
10040
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync6 } from "node:fs";
|
|
10041
|
+
import { resolve as resolve14, dirname as dirname5 } from "node:path";
|
|
10042
|
+
import { homedir as homedir7, hostname } from "node:os";
|
|
9930
10043
|
import YAML5 from "yaml";
|
|
9931
|
-
var
|
|
10044
|
+
var IDENTITY_PATH2 = resolve14(homedir7(), ".0agent", "identity.yaml");
|
|
9932
10045
|
var DEFAULT_IDENTITY = {
|
|
9933
10046
|
name: "User",
|
|
9934
10047
|
device_id: `unknown-device`,
|
|
@@ -9944,8 +10057,8 @@ var IdentityManager = class {
|
|
|
9944
10057
|
* Load or create identity. Call once at daemon startup.
|
|
9945
10058
|
*/
|
|
9946
10059
|
async init() {
|
|
9947
|
-
if (
|
|
9948
|
-
const raw =
|
|
10060
|
+
if (existsSync15(IDENTITY_PATH2)) {
|
|
10061
|
+
const raw = readFileSync13(IDENTITY_PATH2, "utf8");
|
|
9949
10062
|
this.identity = YAML5.parse(raw);
|
|
9950
10063
|
} else {
|
|
9951
10064
|
this.identity = {
|
|
@@ -9996,25 +10109,25 @@ var IdentityManager = class {
|
|
|
9996
10109
|
return lines.join(" ");
|
|
9997
10110
|
}
|
|
9998
10111
|
save() {
|
|
9999
|
-
const dir = dirname5(
|
|
10000
|
-
if (!
|
|
10001
|
-
|
|
10112
|
+
const dir = dirname5(IDENTITY_PATH2);
|
|
10113
|
+
if (!existsSync15(dir)) {
|
|
10114
|
+
mkdirSync6(dir, { recursive: true });
|
|
10002
10115
|
}
|
|
10003
|
-
|
|
10116
|
+
writeFileSync8(IDENTITY_PATH2, YAML5.stringify(this.identity), "utf8");
|
|
10004
10117
|
}
|
|
10005
10118
|
};
|
|
10006
10119
|
|
|
10007
10120
|
// packages/daemon/src/services/TeamManager.ts
|
|
10008
|
-
import { readFileSync as
|
|
10009
|
-
import { resolve as
|
|
10010
|
-
import { homedir as
|
|
10121
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync16, mkdirSync as mkdirSync7 } from "node:fs";
|
|
10122
|
+
import { resolve as resolve15 } from "node:path";
|
|
10123
|
+
import { homedir as homedir8 } from "node:os";
|
|
10011
10124
|
import YAML6 from "yaml";
|
|
10012
|
-
var TEAMS_PATH =
|
|
10125
|
+
var TEAMS_PATH = resolve15(homedir8(), ".0agent", "teams.yaml");
|
|
10013
10126
|
var TeamManager = class {
|
|
10014
10127
|
config;
|
|
10015
10128
|
constructor() {
|
|
10016
|
-
if (
|
|
10017
|
-
this.config = YAML6.parse(
|
|
10129
|
+
if (existsSync16(TEAMS_PATH)) {
|
|
10130
|
+
this.config = YAML6.parse(readFileSync14(TEAMS_PATH, "utf8"));
|
|
10018
10131
|
} else {
|
|
10019
10132
|
this.config = { memberships: [] };
|
|
10020
10133
|
}
|
|
@@ -10069,8 +10182,8 @@ var TeamManager = class {
|
|
|
10069
10182
|
}
|
|
10070
10183
|
}
|
|
10071
10184
|
save() {
|
|
10072
|
-
|
|
10073
|
-
|
|
10185
|
+
mkdirSync7(resolve15(homedir8(), ".0agent"), { recursive: true });
|
|
10186
|
+
writeFileSync9(TEAMS_PATH, YAML6.stringify(this.config), "utf8");
|
|
10074
10187
|
}
|
|
10075
10188
|
};
|
|
10076
10189
|
|
|
@@ -10153,9 +10266,9 @@ var TeamSync = class {
|
|
|
10153
10266
|
};
|
|
10154
10267
|
|
|
10155
10268
|
// packages/daemon/src/services/GitHubMemorySync.ts
|
|
10156
|
-
import { readFileSync as
|
|
10157
|
-
import { resolve as
|
|
10158
|
-
import { homedir as
|
|
10269
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync10, existsSync as existsSync17, readdirSync as readdirSync4 } from "node:fs";
|
|
10270
|
+
import { resolve as resolve16 } from "node:path";
|
|
10271
|
+
import { homedir as homedir9 } from "node:os";
|
|
10159
10272
|
var GITHUB_API = "https://api.github.com";
|
|
10160
10273
|
async function ghFetch(path, token, opts) {
|
|
10161
10274
|
return fetch(`${GITHUB_API}${path}`, {
|
|
@@ -10274,10 +10387,10 @@ var GitHubMemorySync = class {
|
|
|
10274
10387
|
)
|
|
10275
10388
|
);
|
|
10276
10389
|
}
|
|
10277
|
-
const customSkillsDir =
|
|
10278
|
-
if (
|
|
10390
|
+
const customSkillsDir = resolve16(homedir9(), ".0agent", "skills", "custom");
|
|
10391
|
+
if (existsSync17(customSkillsDir)) {
|
|
10279
10392
|
for (const file of readdirSync4(customSkillsDir).filter((f) => f.endsWith(".yaml"))) {
|
|
10280
|
-
const content =
|
|
10393
|
+
const content = readFileSync15(resolve16(customSkillsDir, file), "utf8");
|
|
10281
10394
|
pushes.push(putFile(token, owner, repo, `skills/custom/${file}`, content, commitMsg));
|
|
10282
10395
|
}
|
|
10283
10396
|
}
|
|
@@ -10463,7 +10576,7 @@ var GitHubMemorySync = class {
|
|
|
10463
10576
|
}
|
|
10464
10577
|
async pullCustomSkills() {
|
|
10465
10578
|
const { token, owner, repo } = this.config;
|
|
10466
|
-
const dir =
|
|
10579
|
+
const dir = resolve16(homedir9(), ".0agent", "skills", "custom");
|
|
10467
10580
|
try {
|
|
10468
10581
|
const res = await ghFetch(`/repos/${owner}/${repo}/contents/skills/custom`, token);
|
|
10469
10582
|
if (!res.ok) return;
|
|
@@ -10471,9 +10584,9 @@ var GitHubMemorySync = class {
|
|
|
10471
10584
|
for (const file of files.filter((f) => f.name.endsWith(".yaml"))) {
|
|
10472
10585
|
const content = await getFile(token, owner, repo, `skills/custom/${file.name}`);
|
|
10473
10586
|
if (content) {
|
|
10474
|
-
const { mkdirSync:
|
|
10475
|
-
|
|
10476
|
-
|
|
10587
|
+
const { mkdirSync: mkdirSync12 } = await import("node:fs");
|
|
10588
|
+
mkdirSync12(dir, { recursive: true });
|
|
10589
|
+
writeFileSync10(resolve16(dir, file.name), content, "utf8");
|
|
10477
10590
|
}
|
|
10478
10591
|
}
|
|
10479
10592
|
} catch {
|
|
@@ -11094,7 +11207,7 @@ var SurfaceRouter = class {
|
|
|
11094
11207
|
};
|
|
11095
11208
|
|
|
11096
11209
|
// packages/daemon/src/surfaces/TelegramAdapter.ts
|
|
11097
|
-
import { existsSync as
|
|
11210
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8 } from "node:fs";
|
|
11098
11211
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
11099
11212
|
import { join as join4 } from "node:path";
|
|
11100
11213
|
var TelegramAdapter = class {
|
|
@@ -11308,28 +11421,28 @@ Sessions: ${h.active_sessions} active`
|
|
|
11308
11421
|
const fileUrl = await this._getFileUrl(fileId);
|
|
11309
11422
|
if (!fileUrl) return null;
|
|
11310
11423
|
const tmpDir = join4(tmpdir3(), "0agent-voice");
|
|
11311
|
-
if (!
|
|
11424
|
+
if (!existsSync18(tmpDir)) mkdirSync8(tmpDir, { recursive: true });
|
|
11312
11425
|
const tmpPath = join4(tmpDir, `${fileId}.ogg`);
|
|
11313
11426
|
const wavPath = join4(tmpDir, `${fileId}.wav`);
|
|
11314
11427
|
const res = await fetch(fileUrl);
|
|
11315
11428
|
if (!res.ok) return null;
|
|
11316
11429
|
const buf = await res.arrayBuffer();
|
|
11317
|
-
const { writeFileSync:
|
|
11318
|
-
|
|
11430
|
+
const { writeFileSync: writeFileSync14 } = await import("node:fs");
|
|
11431
|
+
writeFileSync14(tmpPath, Buffer.from(buf));
|
|
11319
11432
|
const { execSync: execSync11 } = await import("node:child_process");
|
|
11320
11433
|
try {
|
|
11321
11434
|
execSync11(`ffmpeg -y -i "${tmpPath}" -ar 16000 -ac 1 "${wavPath}" 2>/dev/null`, { timeout: 3e4 });
|
|
11322
11435
|
} catch {
|
|
11323
11436
|
}
|
|
11324
|
-
const inputFile =
|
|
11437
|
+
const inputFile = existsSync18(wavPath) ? wavPath : tmpPath;
|
|
11325
11438
|
const whisperOut = execSync11(
|
|
11326
11439
|
`whisper "${inputFile}" --model ${this.whisperModel} --output_format txt --output_dir "${tmpDir}" --fp16 False 2>/dev/null`,
|
|
11327
11440
|
{ timeout: 12e4, encoding: "utf8" }
|
|
11328
11441
|
);
|
|
11329
11442
|
const txtPath = inputFile.replace(/\.(ogg|wav)$/, ".txt");
|
|
11330
|
-
if (
|
|
11331
|
-
const { readFileSync:
|
|
11332
|
-
return
|
|
11443
|
+
if (existsSync18(txtPath)) {
|
|
11444
|
+
const { readFileSync: readFileSync19 } = await import("node:fs");
|
|
11445
|
+
return readFileSync19(txtPath, "utf8").trim();
|
|
11333
11446
|
}
|
|
11334
11447
|
return whisperOut?.trim() || null;
|
|
11335
11448
|
} catch {
|
|
@@ -11772,7 +11885,7 @@ import * as readline from "node:readline";
|
|
|
11772
11885
|
|
|
11773
11886
|
// packages/daemon/src/surfaces/WhisperSTT.ts
|
|
11774
11887
|
import { execSync as execSync9, spawnSync as spawnSync5 } from "node:child_process";
|
|
11775
|
-
import { existsSync as
|
|
11888
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync9, readFileSync as readFileSync16 } from "node:fs";
|
|
11776
11889
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
11777
11890
|
import { join as join5, basename as basename2 } from "node:path";
|
|
11778
11891
|
var WhisperSTT = class _WhisperSTT {
|
|
@@ -11790,20 +11903,20 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11790
11903
|
console.warn("[WhisperSTT] No Whisper binary found. Install: pip install openai-whisper");
|
|
11791
11904
|
return null;
|
|
11792
11905
|
}
|
|
11793
|
-
if (!
|
|
11906
|
+
if (!existsSync19(audioPath)) {
|
|
11794
11907
|
console.warn(`[WhisperSTT] Audio file not found: ${audioPath}`);
|
|
11795
11908
|
return null;
|
|
11796
11909
|
}
|
|
11797
11910
|
const outDir = join5(tmpdir4(), "0agent-whisper");
|
|
11798
|
-
if (!
|
|
11911
|
+
if (!existsSync19(outDir)) mkdirSync9(outDir, { recursive: true });
|
|
11799
11912
|
try {
|
|
11800
11913
|
const langFlag = this.language ? `--language ${this.language}` : "";
|
|
11801
11914
|
const cmd = this.binary === "faster-whisper" ? `faster-whisper "${audioPath}" --model ${this.model} ${langFlag} --output_format txt --output_dir "${outDir}"` : `whisper "${audioPath}" --model ${this.model} ${langFlag} --output_format txt --output_dir "${outDir}" --fp16 False`;
|
|
11802
11915
|
execSync9(cmd, { timeout: 18e4, stdio: "pipe" });
|
|
11803
11916
|
const baseName = basename2(audioPath).replace(/\.[^.]+$/, "");
|
|
11804
11917
|
const txtPath = join5(outDir, `${baseName}.txt`);
|
|
11805
|
-
if (
|
|
11806
|
-
return
|
|
11918
|
+
if (existsSync19(txtPath)) {
|
|
11919
|
+
return readFileSync16(txtPath, "utf8").trim();
|
|
11807
11920
|
}
|
|
11808
11921
|
return null;
|
|
11809
11922
|
} catch (err) {
|
|
@@ -11828,14 +11941,14 @@ var WhisperSTT = class _WhisperSTT {
|
|
|
11828
11941
|
};
|
|
11829
11942
|
async function recordAudio(durationSeconds) {
|
|
11830
11943
|
const outDir = join5(tmpdir4(), "0agent-voice");
|
|
11831
|
-
if (!
|
|
11944
|
+
if (!existsSync19(outDir)) mkdirSync9(outDir, { recursive: true });
|
|
11832
11945
|
const outPath = join5(outDir, `recording-${Date.now()}.wav`);
|
|
11833
11946
|
const soxResult = spawnSync5(
|
|
11834
11947
|
"sox",
|
|
11835
11948
|
["-d", "-r", "16000", "-c", "1", "-b", "16", outPath, "trim", "0", String(durationSeconds)],
|
|
11836
11949
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11837
11950
|
);
|
|
11838
|
-
if (soxResult.status === 0 &&
|
|
11951
|
+
if (soxResult.status === 0 && existsSync19(outPath)) return outPath;
|
|
11839
11952
|
const platform3 = process.platform;
|
|
11840
11953
|
let ffmpegDevice;
|
|
11841
11954
|
if (platform3 === "darwin") {
|
|
@@ -11850,7 +11963,7 @@ async function recordAudio(durationSeconds) {
|
|
|
11850
11963
|
["-y", ...ffmpegDevice, "-ar", "16000", "-ac", "1", "-t", String(durationSeconds), outPath],
|
|
11851
11964
|
{ timeout: (durationSeconds + 5) * 1e3, stdio: "pipe" }
|
|
11852
11965
|
);
|
|
11853
|
-
return ffmpegResult.status === 0 &&
|
|
11966
|
+
return ffmpegResult.status === 0 && existsSync19(outPath) ? outPath : null;
|
|
11854
11967
|
}
|
|
11855
11968
|
|
|
11856
11969
|
// packages/daemon/src/surfaces/NativeTTS.ts
|
|
@@ -11878,11 +11991,11 @@ var NativeTTS = class _NativeTTS {
|
|
|
11878
11991
|
if (!this.resolvedEngine) return;
|
|
11879
11992
|
const cleaned = this._clean(text);
|
|
11880
11993
|
if (!cleaned) return;
|
|
11881
|
-
return new Promise((
|
|
11994
|
+
return new Promise((resolve20) => {
|
|
11882
11995
|
const args = this._buildArgs(this.resolvedEngine, cleaned);
|
|
11883
11996
|
const proc = spawn8(this.resolvedEngine, args, { stdio: "ignore" });
|
|
11884
|
-
proc.on("close", () =>
|
|
11885
|
-
proc.on("error", () =>
|
|
11997
|
+
proc.on("close", () => resolve20());
|
|
11998
|
+
proc.on("error", () => resolve20());
|
|
11886
11999
|
});
|
|
11887
12000
|
}
|
|
11888
12001
|
/** Check if any TTS engine is available */
|
|
@@ -12065,7 +12178,7 @@ var VoiceAdapter = class {
|
|
|
12065
12178
|
};
|
|
12066
12179
|
|
|
12067
12180
|
// packages/daemon/src/surfaces/MeetingAdapter.ts
|
|
12068
|
-
import { existsSync as
|
|
12181
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync10, writeFileSync as writeFileSync12 } from "node:fs";
|
|
12069
12182
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
12070
12183
|
import { join as join6 } from "node:path";
|
|
12071
12184
|
import { spawn as spawn9 } from "node:child_process";
|
|
@@ -12093,7 +12206,7 @@ var MeetingAdapter = class {
|
|
|
12093
12206
|
this.triggerPhrases = config.trigger_phrases ?? ["agent,", "hey agent", "ok agent"];
|
|
12094
12207
|
this.contextWindowSeconds = config.context_window_seconds ?? 120;
|
|
12095
12208
|
this.tmpDir = join6(tmpdir5(), "0agent-meeting");
|
|
12096
|
-
if (!
|
|
12209
|
+
if (!existsSync20(this.tmpDir)) mkdirSync10(this.tmpDir, { recursive: true });
|
|
12097
12210
|
this.stt = new WhisperSTT({ model: config.whisper_model ?? "base" });
|
|
12098
12211
|
}
|
|
12099
12212
|
onMessage(handler) {
|
|
@@ -12178,7 +12291,7 @@ ${msg.text}
|
|
|
12178
12291
|
async _captureAndTranscribeChunk(channelId) {
|
|
12179
12292
|
const chunkPath = join6(this.tmpDir, `chunk-${Date.now()}.wav`);
|
|
12180
12293
|
const captured = await this._captureSystemAudio(chunkPath, this.chunkSeconds);
|
|
12181
|
-
if (!captured || !
|
|
12294
|
+
if (!captured || !existsSync20(chunkPath)) return;
|
|
12182
12295
|
const text = await this.stt.transcribe(chunkPath);
|
|
12183
12296
|
if (!text || text.trim().length < 3) return;
|
|
12184
12297
|
const segment = { text: text.trim(), timestamp: Date.now() };
|
|
@@ -12199,7 +12312,7 @@ ${msg.text}
|
|
|
12199
12312
|
}
|
|
12200
12313
|
}
|
|
12201
12314
|
async _captureSystemAudio(outPath, seconds) {
|
|
12202
|
-
return new Promise((
|
|
12315
|
+
return new Promise((resolve20) => {
|
|
12203
12316
|
const platform3 = process.platform;
|
|
12204
12317
|
let args;
|
|
12205
12318
|
if (platform3 === "darwin") {
|
|
@@ -12207,18 +12320,18 @@ ${msg.text}
|
|
|
12207
12320
|
} else if (platform3 === "linux") {
|
|
12208
12321
|
args = ["-y", "-f", "pulse", "-i", "default.monitor", "-ar", "16000", "-ac", "1", "-t", String(seconds), outPath];
|
|
12209
12322
|
} else {
|
|
12210
|
-
|
|
12323
|
+
resolve20(false);
|
|
12211
12324
|
return;
|
|
12212
12325
|
}
|
|
12213
12326
|
const proc = spawn9("ffmpeg", args, { stdio: "pipe" });
|
|
12214
12327
|
this.ffmpegProcess = proc;
|
|
12215
12328
|
proc.on("close", (code) => {
|
|
12216
12329
|
this.ffmpegProcess = null;
|
|
12217
|
-
|
|
12330
|
+
resolve20(code === 0);
|
|
12218
12331
|
});
|
|
12219
12332
|
proc.on("error", () => {
|
|
12220
12333
|
this.ffmpegProcess = null;
|
|
12221
|
-
|
|
12334
|
+
resolve20(false);
|
|
12222
12335
|
});
|
|
12223
12336
|
});
|
|
12224
12337
|
}
|
|
@@ -12277,7 +12390,7 @@ ${fullTranscript}`,
|
|
|
12277
12390
|
const content = `Meeting Transcript
|
|
12278
12391
|
${"=".repeat(40)}
|
|
12279
12392
|
${this.getTranscript()}`;
|
|
12280
|
-
|
|
12393
|
+
writeFileSync12(outPath, content, "utf8");
|
|
12281
12394
|
return outPath;
|
|
12282
12395
|
}
|
|
12283
12396
|
static isAvailable() {
|
|
@@ -12316,13 +12429,13 @@ var ZeroAgentDaemon = class {
|
|
|
12316
12429
|
startedAt = 0;
|
|
12317
12430
|
pidFilePath;
|
|
12318
12431
|
constructor() {
|
|
12319
|
-
this.pidFilePath =
|
|
12432
|
+
this.pidFilePath = resolve18(homedir10(), ".0agent", "daemon.pid");
|
|
12320
12433
|
}
|
|
12321
12434
|
async start(opts) {
|
|
12322
12435
|
this.config = await loadConfig(opts?.config_path);
|
|
12323
|
-
const dotDir =
|
|
12324
|
-
if (!
|
|
12325
|
-
|
|
12436
|
+
const dotDir = resolve18(homedir10(), ".0agent");
|
|
12437
|
+
if (!existsSync22(dotDir)) {
|
|
12438
|
+
mkdirSync11(dotDir, { recursive: true });
|
|
12326
12439
|
}
|
|
12327
12440
|
this.adapter = new SQLiteAdapter({ db_path: this.config.graph.db_path });
|
|
12328
12441
|
this.graph = new KnowledgeGraph(this.adapter);
|
|
@@ -12395,10 +12508,10 @@ var ZeroAgentDaemon = class {
|
|
|
12395
12508
|
console.log(`[0agent] Teams: ${teams.map((t) => t.team_name).join(", ")}`);
|
|
12396
12509
|
}
|
|
12397
12510
|
const _daemonFile = fileURLToPath3(import.meta.url);
|
|
12398
|
-
const _agentRoot =
|
|
12511
|
+
const _agentRoot = resolve18(dirname7(_daemonFile), "..");
|
|
12399
12512
|
let agentRoot;
|
|
12400
12513
|
try {
|
|
12401
|
-
const _pkg = JSON.parse(
|
|
12514
|
+
const _pkg = JSON.parse(readFileSync18(resolve18(_agentRoot, "package.json"), "utf8"));
|
|
12402
12515
|
if (_pkg.name === "0agent") agentRoot = _agentRoot;
|
|
12403
12516
|
} catch {
|
|
12404
12517
|
}
|
|
@@ -12550,7 +12663,7 @@ var ZeroAgentDaemon = class {
|
|
|
12550
12663
|
}
|
|
12551
12664
|
});
|
|
12552
12665
|
await this.httpServer.start();
|
|
12553
|
-
|
|
12666
|
+
writeFileSync13(this.pidFilePath, String(process.pid), "utf8");
|
|
12554
12667
|
console.log(
|
|
12555
12668
|
`[0agent] Daemon started on ${this.config.server.host}:${this.config.server.port} (PID: ${process.pid})`
|
|
12556
12669
|
);
|
|
@@ -12602,7 +12715,7 @@ var ZeroAgentDaemon = class {
|
|
|
12602
12715
|
this.graph = null;
|
|
12603
12716
|
}
|
|
12604
12717
|
this.adapter = null;
|
|
12605
|
-
if (
|
|
12718
|
+
if (existsSync22(this.pidFilePath)) {
|
|
12606
12719
|
try {
|
|
12607
12720
|
unlinkSync4(this.pidFilePath);
|
|
12608
12721
|
} catch {
|
|
@@ -12632,11 +12745,11 @@ var ZeroAgentDaemon = class {
|
|
|
12632
12745
|
};
|
|
12633
12746
|
|
|
12634
12747
|
// packages/daemon/src/start.ts
|
|
12635
|
-
import { resolve as
|
|
12636
|
-
import { homedir as
|
|
12637
|
-
import { existsSync as
|
|
12638
|
-
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ??
|
|
12639
|
-
if (!
|
|
12748
|
+
import { resolve as resolve19 } from "node:path";
|
|
12749
|
+
import { homedir as homedir11 } from "node:os";
|
|
12750
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
12751
|
+
var CONFIG_PATH = process.env["ZEROAGENT_CONFIG"] ?? resolve19(homedir11(), ".0agent", "config.yaml");
|
|
12752
|
+
if (!existsSync23(CONFIG_PATH)) {
|
|
12640
12753
|
console.error(`
|
|
12641
12754
|
0agent is not initialised.
|
|
12642
12755
|
|