open-agents-ai 0.10.8 → 0.11.1
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 +200 -80
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1854,15 +1854,26 @@ var init_memory_read = __esm({
|
|
|
1854
1854
|
durationMs: performance.now() - start
|
|
1855
1855
|
};
|
|
1856
1856
|
}
|
|
1857
|
+
const entry = entries[key];
|
|
1858
|
+
const artifactTag = entry?.artifactId ? ` [artifact: ${entry.artifactId}]` : "";
|
|
1857
1859
|
return {
|
|
1858
1860
|
success: true,
|
|
1859
|
-
output: JSON.stringify(
|
|
1861
|
+
output: JSON.stringify(entry, null, 2) + artifactTag,
|
|
1860
1862
|
durationMs: performance.now() - start
|
|
1861
1863
|
};
|
|
1862
1864
|
}
|
|
1865
|
+
const keys = Object.keys(entries);
|
|
1866
|
+
const summary = keys.map((k) => {
|
|
1867
|
+
const e = entries[k];
|
|
1868
|
+
const aid = e?.artifactId ? ` [${e.artifactId}]` : "";
|
|
1869
|
+
return ` ${k}${aid}`;
|
|
1870
|
+
}).join("\n");
|
|
1863
1871
|
return {
|
|
1864
1872
|
success: true,
|
|
1865
|
-
output:
|
|
1873
|
+
output: `Topic: ${topic} (${keys.length} entries)
|
|
1874
|
+
${summary}
|
|
1875
|
+
|
|
1876
|
+
${JSON.stringify(entries, null, 2)}`,
|
|
1866
1877
|
durationMs: performance.now() - start
|
|
1867
1878
|
};
|
|
1868
1879
|
} catch (error) {
|
|
@@ -1881,6 +1892,7 @@ var init_memory_read = __esm({
|
|
|
1881
1892
|
// packages/execution/dist/tools/memory-write.js
|
|
1882
1893
|
import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir2 } from "node:fs/promises";
|
|
1883
1894
|
import { resolve as resolve7, join as join4 } from "node:path";
|
|
1895
|
+
import { randomBytes } from "node:crypto";
|
|
1884
1896
|
var MemoryWriteTool;
|
|
1885
1897
|
var init_memory_write = __esm({
|
|
1886
1898
|
"packages/execution/dist/tools/memory-write.js"() {
|
|
@@ -1927,15 +1939,32 @@ var init_memory_write = __esm({
|
|
|
1927
1939
|
entries = JSON.parse(raw);
|
|
1928
1940
|
} catch {
|
|
1929
1941
|
}
|
|
1942
|
+
const artifactId = `mem-${randomBytes(6).toString("hex")}`;
|
|
1930
1943
|
entries[key] = {
|
|
1931
1944
|
value,
|
|
1932
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1945
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1946
|
+
artifactId
|
|
1933
1947
|
};
|
|
1934
1948
|
await writeFile3(topicFile, JSON.stringify(entries, null, 2), "utf-8");
|
|
1935
1949
|
}
|
|
1950
|
+
const provenanceDir = resolve7(this.workingDir, ".oa", "provenance");
|
|
1951
|
+
try {
|
|
1952
|
+
await mkdir2(provenanceDir, { recursive: true });
|
|
1953
|
+
const provRecord = {
|
|
1954
|
+
type: "memory_write",
|
|
1955
|
+
topic,
|
|
1956
|
+
key,
|
|
1957
|
+
artifactId: `mem-${randomBytes(6).toString("hex")}`,
|
|
1958
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1959
|
+
source: "agent"
|
|
1960
|
+
};
|
|
1961
|
+
const provFile = join4(provenanceDir, `${Date.now()}-memory-write.json`);
|
|
1962
|
+
await writeFile3(provFile, JSON.stringify(provRecord, null, 2), "utf-8");
|
|
1963
|
+
} catch {
|
|
1964
|
+
}
|
|
1936
1965
|
return {
|
|
1937
1966
|
success: true,
|
|
1938
|
-
output: `Stored memory: ${topic}.${key}`,
|
|
1967
|
+
output: `Stored memory: ${topic}.${key} [artifact: mem-${Date.now().toString(36)}]`,
|
|
1939
1968
|
durationMs: performance.now() - start
|
|
1940
1969
|
};
|
|
1941
1970
|
} catch (error) {
|
|
@@ -7491,6 +7520,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
7491
7520
|
case "verbose":
|
|
7492
7521
|
case "v":
|
|
7493
7522
|
ctx.setVerbose(!ctx.config.verbose);
|
|
7523
|
+
ctx.saveSettings({ verbose: ctx.config.verbose });
|
|
7494
7524
|
renderInfo(`Verbose mode: ${ctx.config.verbose ? "on" : "off"}`);
|
|
7495
7525
|
return "handled";
|
|
7496
7526
|
case "config":
|
|
@@ -7526,9 +7556,12 @@ async function handleSlashCommand(input, ctx) {
|
|
|
7526
7556
|
case "voice": {
|
|
7527
7557
|
if (arg) {
|
|
7528
7558
|
const msg = await ctx.voiceSetModel(arg);
|
|
7559
|
+
ctx.saveSettings({ voice: true, voiceModel: arg });
|
|
7529
7560
|
renderInfo(msg);
|
|
7530
7561
|
} else {
|
|
7531
7562
|
const msg = await ctx.voiceToggle();
|
|
7563
|
+
const isOn = msg.toLowerCase().includes("enabled") || msg.toLowerCase().includes("on");
|
|
7564
|
+
ctx.saveSettings({ voice: isOn });
|
|
7532
7565
|
renderInfo(msg);
|
|
7533
7566
|
}
|
|
7534
7567
|
return "handled";
|
|
@@ -7626,6 +7659,7 @@ async function handleEndpoint(arg, ctx) {
|
|
|
7626
7659
|
if (apiKey) {
|
|
7627
7660
|
setConfigValue("apiKey", apiKey);
|
|
7628
7661
|
}
|
|
7662
|
+
ctx.saveSettings({ backendUrl: url, backendType, ...apiKey ? { apiKey } : {} });
|
|
7629
7663
|
process.stdout.write(`
|
|
7630
7664
|
${c2.green("\u2714")} Endpoint updated and saved:
|
|
7631
7665
|
`);
|
|
@@ -7707,6 +7741,7 @@ async function switchModel(query, ctx) {
|
|
|
7707
7741
|
}
|
|
7708
7742
|
const oldModel = ctx.config.model;
|
|
7709
7743
|
ctx.setModel(match.name);
|
|
7744
|
+
ctx.saveSettings({ model: match.name });
|
|
7710
7745
|
renderModelSwitch(oldModel, match.name);
|
|
7711
7746
|
} catch (err) {
|
|
7712
7747
|
renderError(`Failed to switch model: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -8112,6 +8147,7 @@ var init_setup = __esm({
|
|
|
8112
8147
|
// packages/cli/dist/tui/oa-directory.js
|
|
8113
8148
|
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
|
|
8114
8149
|
import { join as join14, relative as relative2, basename as basename2, extname as extname4 } from "node:path";
|
|
8150
|
+
import { homedir as homedir4 } from "node:os";
|
|
8115
8151
|
function initOaDirectory(repoRoot) {
|
|
8116
8152
|
const oaPath = join14(repoRoot, OA_DIR);
|
|
8117
8153
|
for (const sub of SUBDIRS) {
|
|
@@ -8122,6 +8158,45 @@ function initOaDirectory(repoRoot) {
|
|
|
8122
8158
|
function hasOaDirectory(repoRoot) {
|
|
8123
8159
|
return existsSync9(join14(repoRoot, OA_DIR, "index"));
|
|
8124
8160
|
}
|
|
8161
|
+
function loadProjectSettings(repoRoot) {
|
|
8162
|
+
const settingsPath = join14(repoRoot, OA_DIR, "settings.json");
|
|
8163
|
+
try {
|
|
8164
|
+
if (existsSync9(settingsPath)) {
|
|
8165
|
+
return JSON.parse(readFileSync7(settingsPath, "utf-8"));
|
|
8166
|
+
}
|
|
8167
|
+
} catch {
|
|
8168
|
+
}
|
|
8169
|
+
return {};
|
|
8170
|
+
}
|
|
8171
|
+
function saveProjectSettings(repoRoot, settings) {
|
|
8172
|
+
const oaPath = join14(repoRoot, OA_DIR);
|
|
8173
|
+
mkdirSync4(oaPath, { recursive: true });
|
|
8174
|
+
const existing = loadProjectSettings(repoRoot);
|
|
8175
|
+
const merged = { ...existing, ...settings };
|
|
8176
|
+
writeFileSync4(join14(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
8177
|
+
}
|
|
8178
|
+
function loadGlobalSettings() {
|
|
8179
|
+
const settingsPath = join14(homedir4(), ".open-agents", "settings.json");
|
|
8180
|
+
try {
|
|
8181
|
+
if (existsSync9(settingsPath)) {
|
|
8182
|
+
return JSON.parse(readFileSync7(settingsPath, "utf-8"));
|
|
8183
|
+
}
|
|
8184
|
+
} catch {
|
|
8185
|
+
}
|
|
8186
|
+
return {};
|
|
8187
|
+
}
|
|
8188
|
+
function saveGlobalSettings(settings) {
|
|
8189
|
+
const dir = join14(homedir4(), ".open-agents");
|
|
8190
|
+
mkdirSync4(dir, { recursive: true });
|
|
8191
|
+
const existing = loadGlobalSettings();
|
|
8192
|
+
const merged = { ...existing, ...settings };
|
|
8193
|
+
writeFileSync4(join14(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
8194
|
+
}
|
|
8195
|
+
function resolveSettings(repoRoot) {
|
|
8196
|
+
const global = loadGlobalSettings();
|
|
8197
|
+
const project = loadProjectSettings(repoRoot);
|
|
8198
|
+
return { ...global, ...project };
|
|
8199
|
+
}
|
|
8125
8200
|
function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
8126
8201
|
const found = [];
|
|
8127
8202
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8364,7 +8439,7 @@ var init_oa_directory = __esm({
|
|
|
8364
8439
|
"packages/cli/dist/tui/oa-directory.js"() {
|
|
8365
8440
|
"use strict";
|
|
8366
8441
|
OA_DIR = ".oa";
|
|
8367
|
-
SUBDIRS = ["memory", "index", "context", "history"];
|
|
8442
|
+
SUBDIRS = ["memory", "index", "context", "history", "notes", "embedded", "provenance"];
|
|
8368
8443
|
CONTEXT_FILES = [
|
|
8369
8444
|
"AGENTS.md",
|
|
8370
8445
|
"OA.md",
|
|
@@ -8401,7 +8476,7 @@ var init_oa_directory = __esm({
|
|
|
8401
8476
|
import { existsSync as existsSync10, readFileSync as readFileSync8, readdirSync as readdirSync5 } from "node:fs";
|
|
8402
8477
|
import { join as join15, basename as basename3 } from "node:path";
|
|
8403
8478
|
import { execSync as execSync9 } from "node:child_process";
|
|
8404
|
-
import { homedir as
|
|
8479
|
+
import { homedir as homedir5, platform, release } from "node:os";
|
|
8405
8480
|
function loadProjectFiles(repoRoot) {
|
|
8406
8481
|
const discovered = discoverContextFiles(repoRoot);
|
|
8407
8482
|
if (discovered.length === 0)
|
|
@@ -8473,7 +8548,7 @@ function loadMemoryContext(repoRoot) {
|
|
|
8473
8548
|
if (legacyEntries)
|
|
8474
8549
|
sections.push(legacyEntries);
|
|
8475
8550
|
}
|
|
8476
|
-
const globalMemDir = join15(
|
|
8551
|
+
const globalMemDir = join15(homedir5(), ".open-agents", "memory");
|
|
8477
8552
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
8478
8553
|
if (globalEntries)
|
|
8479
8554
|
sections.push(globalEntries);
|
|
@@ -8586,8 +8661,30 @@ var init_project_context = __esm({
|
|
|
8586
8661
|
function fg(code, text) {
|
|
8587
8662
|
return isTTY3 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
|
|
8588
8663
|
}
|
|
8664
|
+
function displayWidth(str) {
|
|
8665
|
+
let w = 0;
|
|
8666
|
+
for (const ch of str) {
|
|
8667
|
+
const cp = ch.codePointAt(0);
|
|
8668
|
+
if (cp >= 4352 && cp <= 4447 || // Hangul Jamo
|
|
8669
|
+
cp >= 11904 && cp <= 12350 || // CJK Radicals, Kangxi, CJK Symbols
|
|
8670
|
+
cp >= 12352 && cp <= 13247 || // Hiragana, Katakana, CJK Compat
|
|
8671
|
+
cp >= 13312 && cp <= 19903 || // CJK Ext A
|
|
8672
|
+
cp >= 19968 && cp <= 42191 || // CJK Unified, Yi
|
|
8673
|
+
cp >= 44032 && cp <= 55215 || // Hangul Syllables
|
|
8674
|
+
cp >= 63744 && cp <= 64255 || // CJK Compat Ideographs
|
|
8675
|
+
cp >= 65072 && cp <= 65135 || // CJK Compat Forms
|
|
8676
|
+
cp >= 65281 && cp <= 65376 || // Fullwidth Forms
|
|
8677
|
+
cp >= 65504 && cp <= 65510 || // Fullwidth Signs
|
|
8678
|
+
cp >= 131072 && cp <= 195103) {
|
|
8679
|
+
w += 2;
|
|
8680
|
+
} else {
|
|
8681
|
+
w += 1;
|
|
8682
|
+
}
|
|
8683
|
+
}
|
|
8684
|
+
return w;
|
|
8685
|
+
}
|
|
8589
8686
|
function buildPlainRibbon(phrases, repeatWidth) {
|
|
8590
|
-
const separator = "
|
|
8687
|
+
const separator = " : ";
|
|
8591
8688
|
let plain = "";
|
|
8592
8689
|
while (plain.length < repeatWidth * 3) {
|
|
8593
8690
|
for (const p of phrases) {
|
|
@@ -8623,70 +8720,67 @@ var init_carousel = __esm({
|
|
|
8623
8720
|
{ text: "imagine freely", color: 219 },
|
|
8624
8721
|
{ text: "liberate creativity", color: 111 },
|
|
8625
8722
|
// Spanish
|
|
8626
|
-
{ text: "libertad de
|
|
8723
|
+
{ text: "libertad de informacion", color: 214 },
|
|
8627
8724
|
{ text: "crear libremente", color: 208 },
|
|
8628
|
-
{ text: "
|
|
8629
|
-
{ text: "
|
|
8630
|
-
{ text: "
|
|
8725
|
+
{ text: "codigo abierto", color: 220 },
|
|
8726
|
+
{ text: "se creativo", color: 226 },
|
|
8727
|
+
{ text: "imaginacion sin limites", color: 215 },
|
|
8631
8728
|
// French
|
|
8632
|
-
{ text: "
|
|
8633
|
-
{ text: "
|
|
8729
|
+
{ text: "creer librement", color: 171 },
|
|
8730
|
+
{ text: "liberte d'expression", color: 177 },
|
|
8634
8731
|
{ text: "source ouverte", color: 141 },
|
|
8635
8732
|
{ text: "imaginer sans contrainte", color: 183 },
|
|
8636
8733
|
// German
|
|
8637
8734
|
{ text: "Freiheit der Muster", color: 77 },
|
|
8638
8735
|
{ text: "frei erschaffen", color: 78 },
|
|
8639
8736
|
{ text: "offene Quelle", color: 114 },
|
|
8640
|
-
{ text: "grenzenlose
|
|
8737
|
+
{ text: "grenzenlose Kreativitat", color: 150 },
|
|
8641
8738
|
// Japanese
|
|
8642
|
-
{ text: "
|
|
8643
|
-
{ text: "
|
|
8644
|
-
{ text: "
|
|
8645
|
-
{ text: "
|
|
8739
|
+
{ text: "jiyuu ni souzou suru", color: 204 },
|
|
8740
|
+
{ text: "kaigen no seishin", color: 210 },
|
|
8741
|
+
{ text: "seiyaku naki souzouryoku", color: 203 },
|
|
8742
|
+
{ text: "chishiki wo kyouyuu", color: 209 },
|
|
8646
8743
|
// Korean
|
|
8647
|
-
{ text: "
|
|
8648
|
-
{ text: "
|
|
8649
|
-
{ text: "
|
|
8650
|
-
// Chinese
|
|
8651
|
-
{ text: "\u958B\u6E90\u81EA\u7531", color: 167 },
|
|
8652
|
-
{ text: "\u81EA\u7531\u5275\u4F5C", color: 173 },
|
|
8653
|
-
{ text: "\u77E5\u8B58\u5171\u4EAB", color: 161 },
|
|
8654
|
-
{ text: "\u7121\u9650\u60F3\u50CF", color: 131 },
|
|
8744
|
+
{ text: "jayuroun changjak", color: 105 },
|
|
8745
|
+
{ text: "opeunsoseu jeongsin", color: 99 },
|
|
8746
|
+
{ text: "yeonggam eul nanuda", color: 135 },
|
|
8655
8747
|
// Russian
|
|
8656
|
-
{ text: "
|
|
8657
|
-
{ text: "
|
|
8658
|
-
{ text: "
|
|
8748
|
+
{ text: "svoboda tvorchestva", color: 73 },
|
|
8749
|
+
{ text: "otkrytyy iskhodnyy kod", color: 67 },
|
|
8750
|
+
{ text: "sozdavay svobodno", color: 109 },
|
|
8659
8751
|
// Portuguese
|
|
8660
8752
|
{ text: "liberdade de criar", color: 179 },
|
|
8661
|
-
{ text: "
|
|
8662
|
-
{ text: "
|
|
8753
|
+
{ text: "codigo aberto", color: 185 },
|
|
8754
|
+
{ text: "imaginacao sem fronteiras", color: 186 },
|
|
8663
8755
|
// Italian
|
|
8664
8756
|
{ text: "creare liberamente", color: 144 },
|
|
8665
|
-
{ text: "
|
|
8666
|
-
// Hindi
|
|
8667
|
-
{ text: "\u0916\u0941\u0932\u0940 \u0938\u094B\u091A", color: 198 },
|
|
8668
|
-
{ text: "\u092E\u0941\u0915\u094D\u0924 \u0930\u091A\u0928\u093E", color: 199 },
|
|
8669
|
-
// Arabic
|
|
8670
|
-
{ text: "\u062D\u0631\u064A\u0629 \u0627\u0644\u0625\u0628\u062F\u0627\u0639", color: 222 },
|
|
8671
|
-
{ text: "\u0645\u0635\u062F\u0631 \u0645\u0641\u062A\u0648\u062D", color: 228 },
|
|
8757
|
+
{ text: "liberta di espressione", color: 180 },
|
|
8672
8758
|
// Turkish
|
|
8673
|
-
{ text: "
|
|
8674
|
-
{ text: "
|
|
8759
|
+
{ text: "ozgurce yarat", color: 156 },
|
|
8760
|
+
{ text: "acik kaynak", color: 192 },
|
|
8675
8761
|
// Swedish
|
|
8676
8762
|
{ text: "skapa fritt", color: 116 },
|
|
8677
|
-
{ text: "
|
|
8763
|
+
{ text: "oppen kallkod", color: 122 },
|
|
8678
8764
|
// Dutch
|
|
8679
|
-
{ text: "vrij
|
|
8765
|
+
{ text: "vrij creeren", color: 152 },
|
|
8680
8766
|
// Polish
|
|
8681
|
-
{ text: "
|
|
8767
|
+
{ text: "tworz swobodnie", color: 188 },
|
|
8682
8768
|
// Greek
|
|
8683
|
-
{ text: "
|
|
8769
|
+
{ text: "dimiourgia elefthera", color: 75 },
|
|
8770
|
+
// Hindi
|
|
8771
|
+
{ text: "khuli soch", color: 198 },
|
|
8772
|
+
{ text: "mukt rachna", color: 199 },
|
|
8773
|
+
// Arabic
|
|
8774
|
+
{ text: "hurriyat al-ibdaa", color: 222 },
|
|
8775
|
+
{ text: "masdar maftuh", color: 228 }
|
|
8684
8776
|
];
|
|
8685
8777
|
Carousel = class {
|
|
8686
8778
|
rows;
|
|
8687
8779
|
timer = null;
|
|
8688
8780
|
width;
|
|
8689
8781
|
lineCount = 3;
|
|
8782
|
+
/** Total rows reserved at top: 3 carousel + 1 blank separator */
|
|
8783
|
+
reservedRows = 4;
|
|
8690
8784
|
started = false;
|
|
8691
8785
|
resizeHandler = null;
|
|
8692
8786
|
constructor() {
|
|
@@ -8696,11 +8790,8 @@ var init_carousel = __esm({
|
|
|
8696
8790
|
const indices2 = Array.from({ length: PHRASES.length }, (_, i) => i).sort(() => Math.random() - 0.5);
|
|
8697
8791
|
this.rows = [
|
|
8698
8792
|
createRow(indices0, 2, -1),
|
|
8699
|
-
// fast left
|
|
8700
8793
|
createRow(indices1, 1, 1),
|
|
8701
|
-
// medium right
|
|
8702
8794
|
createRow(indices2, 1.5, -1)
|
|
8703
|
-
// slow-medium left
|
|
8704
8795
|
];
|
|
8705
8796
|
this.rebuildRibbons();
|
|
8706
8797
|
}
|
|
@@ -8711,13 +8802,8 @@ var init_carousel = __esm({
|
|
|
8711
8802
|
}
|
|
8712
8803
|
/**
|
|
8713
8804
|
* Start the animation.
|
|
8714
|
-
*
|
|
8715
|
-
*
|
|
8716
|
-
* 2. Sets DECSTBM scroll region to row 4+ (everything below carousel)
|
|
8717
|
-
* 3. Moves cursor into the scroll region
|
|
8718
|
-
* 4. Starts animation timer that writes ONLY to rows 1-3
|
|
8719
|
-
*
|
|
8720
|
-
* The cursor never leaves the scroll region, so readline works perfectly.
|
|
8805
|
+
* Reserves rows 1-3 for carousel, row 4 as blank separator.
|
|
8806
|
+
* Sets scroll region to row 5+ for all content/readline.
|
|
8721
8807
|
*/
|
|
8722
8808
|
start() {
|
|
8723
8809
|
if (!isTTY3)
|
|
@@ -8725,17 +8811,17 @@ var init_carousel = __esm({
|
|
|
8725
8811
|
this.started = true;
|
|
8726
8812
|
const termRows = process.stdout.rows ?? 24;
|
|
8727
8813
|
process.stdout.write("\x1B[1;1H");
|
|
8728
|
-
for (let i = 0; i < this.
|
|
8814
|
+
for (let i = 0; i < this.reservedRows; i++) {
|
|
8729
8815
|
process.stdout.write("\x1B[2K\n");
|
|
8730
8816
|
}
|
|
8731
|
-
process.stdout.write(`\x1B[${this.
|
|
8732
|
-
process.stdout.write(`\x1B[${this.
|
|
8817
|
+
process.stdout.write(`\x1B[${this.reservedRows + 1};${termRows}r`);
|
|
8818
|
+
process.stdout.write(`\x1B[${this.reservedRows + 1};1H`);
|
|
8733
8819
|
this.resizeHandler = () => {
|
|
8734
8820
|
this.width = process.stdout.columns ?? 80;
|
|
8735
8821
|
const newRows = process.stdout.rows ?? 24;
|
|
8736
8822
|
this.rebuildRibbons();
|
|
8737
8823
|
if (this.started) {
|
|
8738
|
-
process.stdout.write(`\x1B[${this.
|
|
8824
|
+
process.stdout.write(`\x1B[${this.reservedRows + 1};${newRows}r`);
|
|
8739
8825
|
}
|
|
8740
8826
|
};
|
|
8741
8827
|
process.stdout.on("resize", this.resizeHandler);
|
|
@@ -8749,40 +8835,41 @@ var init_carousel = __esm({
|
|
|
8749
8835
|
}
|
|
8750
8836
|
this.renderFrame();
|
|
8751
8837
|
}, 66);
|
|
8752
|
-
return this.
|
|
8838
|
+
return this.reservedRows;
|
|
8753
8839
|
}
|
|
8754
8840
|
/**
|
|
8755
|
-
* Render one animation frame.
|
|
8756
|
-
*
|
|
8757
|
-
* Uses save/restore cursor (DECSC/DECRC) to briefly visit rows 1-3,
|
|
8758
|
-
* then return. Because the scroll region is set to row 4+, the cursor
|
|
8759
|
-
* restore puts it back exactly where readline expects it.
|
|
8841
|
+
* Render one animation frame into rows 1-3 only.
|
|
8842
|
+
* Row 4 is left blank as a separator.
|
|
8760
8843
|
*/
|
|
8761
8844
|
renderFrame() {
|
|
8762
8845
|
if (!isTTY3)
|
|
8763
8846
|
return;
|
|
8764
8847
|
let buf = "\x1B7";
|
|
8848
|
+
buf += "\x1B[?7l";
|
|
8765
8849
|
for (let i = 0; i < this.rows.length; i++) {
|
|
8766
8850
|
const line = this.extractWindow(this.rows[i]);
|
|
8767
8851
|
buf += `\x1B[${i + 1};1H\x1B[2K${line}`;
|
|
8768
8852
|
}
|
|
8853
|
+
buf += `\x1B[4;1H\x1B[2K`;
|
|
8854
|
+
buf += "\x1B[?7h";
|
|
8769
8855
|
buf += "\x1B8";
|
|
8770
8856
|
process.stdout.write(buf);
|
|
8771
8857
|
}
|
|
8772
8858
|
/**
|
|
8773
8859
|
* Extract a terminal-width colored window from a scrolling ribbon.
|
|
8860
|
+
* Uses column-aware width to prevent CJK/fullwidth character overflow.
|
|
8774
8861
|
*/
|
|
8775
8862
|
extractWindow(row) {
|
|
8776
|
-
const
|
|
8863
|
+
const maxCols = this.width;
|
|
8777
8864
|
const plain = row.renderedPlain;
|
|
8778
8865
|
if (!plain)
|
|
8779
8866
|
return "";
|
|
8780
8867
|
let start = Math.floor(Math.abs(row.offset)) % plain.length;
|
|
8781
8868
|
if (start < 0)
|
|
8782
8869
|
start += plain.length;
|
|
8783
|
-
const separator = "
|
|
8870
|
+
const separator = " : ";
|
|
8784
8871
|
let coloredLine = "";
|
|
8785
|
-
let
|
|
8872
|
+
let colCount = 0;
|
|
8786
8873
|
let charInPhrase = 0;
|
|
8787
8874
|
let skipChars = start;
|
|
8788
8875
|
const phrases = row.phrases;
|
|
@@ -8797,20 +8884,25 @@ var init_carousel = __esm({
|
|
|
8797
8884
|
skipChars -= fullText.length;
|
|
8798
8885
|
fullIdx++;
|
|
8799
8886
|
}
|
|
8800
|
-
while (
|
|
8887
|
+
while (colCount < maxCols) {
|
|
8801
8888
|
const p = phrases[fullIdx % phrases.length];
|
|
8802
8889
|
const fullText = p.text + separator;
|
|
8803
8890
|
const remaining = fullText.slice(charInPhrase);
|
|
8804
8891
|
for (const ch of remaining) {
|
|
8805
|
-
|
|
8892
|
+
const chWidth = displayWidth(ch);
|
|
8893
|
+
if (colCount + chWidth > maxCols) {
|
|
8894
|
+
if (colCount < maxCols)
|
|
8895
|
+
coloredLine += " ";
|
|
8896
|
+
colCount = maxCols;
|
|
8806
8897
|
break;
|
|
8898
|
+
}
|
|
8807
8899
|
const inPhrase = charInPhrase < p.text.length;
|
|
8808
8900
|
if (inPhrase) {
|
|
8809
8901
|
coloredLine += fg(p.color, ch);
|
|
8810
8902
|
} else {
|
|
8811
8903
|
coloredLine += `\x1B[2m${ch}\x1B[0m`;
|
|
8812
8904
|
}
|
|
8813
|
-
|
|
8905
|
+
colCount += chWidth;
|
|
8814
8906
|
charInPhrase++;
|
|
8815
8907
|
}
|
|
8816
8908
|
fullIdx++;
|
|
@@ -8819,7 +8911,7 @@ var init_carousel = __esm({
|
|
|
8819
8911
|
return coloredLine;
|
|
8820
8912
|
}
|
|
8821
8913
|
/**
|
|
8822
|
-
* Stop the animation, clear
|
|
8914
|
+
* Stop the animation, clear rows 1-4, reset scroll region.
|
|
8823
8915
|
*/
|
|
8824
8916
|
stop() {
|
|
8825
8917
|
if (this.timer) {
|
|
@@ -8833,7 +8925,7 @@ var init_carousel = __esm({
|
|
|
8833
8925
|
if (!isTTY3 || !this.started)
|
|
8834
8926
|
return;
|
|
8835
8927
|
let buf = "\x1B7";
|
|
8836
|
-
for (let i = 0; i < this.
|
|
8928
|
+
for (let i = 0; i < this.reservedRows; i++) {
|
|
8837
8929
|
buf += `\x1B[${i + 1};1H\x1B[2K`;
|
|
8838
8930
|
}
|
|
8839
8931
|
buf += "\x1B[r";
|
|
@@ -8841,7 +8933,6 @@ var init_carousel = __esm({
|
|
|
8841
8933
|
process.stdout.write(buf);
|
|
8842
8934
|
this.started = false;
|
|
8843
8935
|
}
|
|
8844
|
-
/** Check if carousel is running */
|
|
8845
8936
|
get isRunning() {
|
|
8846
8937
|
return this.timer !== null;
|
|
8847
8938
|
}
|
|
@@ -8852,7 +8943,7 @@ var init_carousel = __esm({
|
|
|
8852
8943
|
// packages/cli/dist/tui/voice.js
|
|
8853
8944
|
import { existsSync as existsSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readFileSync as readFileSync9, unlinkSync } from "node:fs";
|
|
8854
8945
|
import { join as join16 } from "node:path";
|
|
8855
|
-
import { homedir as
|
|
8946
|
+
import { homedir as homedir6, tmpdir as tmpdir2, platform as platform2 } from "node:os";
|
|
8856
8947
|
import { execSync as execSync10, spawn as nodeSpawn } from "node:child_process";
|
|
8857
8948
|
import { createRequire } from "node:module";
|
|
8858
8949
|
function modelDir(id) {
|
|
@@ -8971,7 +9062,7 @@ var init_voice = __esm({
|
|
|
8971
9062
|
configUrl: "https://raw.githubusercontent.com/robit-man/combine_overwatch_onnx/main/overwatch.onnx.json"
|
|
8972
9063
|
}
|
|
8973
9064
|
};
|
|
8974
|
-
VOICE_DIR = join16(
|
|
9065
|
+
VOICE_DIR = join16(homedir6(), ".open-agents", "voice");
|
|
8975
9066
|
MODELS_DIR = join16(VOICE_DIR, "models");
|
|
8976
9067
|
VoiceEngine = class {
|
|
8977
9068
|
enabled = false;
|
|
@@ -9620,6 +9711,19 @@ function startTask(task, config, repoRoot, voice) {
|
|
|
9620
9711
|
}
|
|
9621
9712
|
async function startInteractive(config, repoPath) {
|
|
9622
9713
|
const repoRoot = resolve11(repoPath ?? cwd());
|
|
9714
|
+
initOaDirectory(repoRoot);
|
|
9715
|
+
const savedSettings = resolveSettings(repoRoot);
|
|
9716
|
+
if (savedSettings.model)
|
|
9717
|
+
config = { ...config, model: savedSettings.model };
|
|
9718
|
+
if (savedSettings.backendUrl)
|
|
9719
|
+
config = { ...config, backendUrl: savedSettings.backendUrl };
|
|
9720
|
+
if (savedSettings.backendType && ["ollama", "vllm", "fake"].includes(savedSettings.backendType)) {
|
|
9721
|
+
config = { ...config, backendType: savedSettings.backendType };
|
|
9722
|
+
}
|
|
9723
|
+
if (savedSettings.apiKey)
|
|
9724
|
+
config = { ...config, apiKey: savedSettings.apiKey };
|
|
9725
|
+
if (savedSettings.verbose !== void 0)
|
|
9726
|
+
config = { ...config, verbose: savedSettings.verbose };
|
|
9623
9727
|
const needsSetup = isFirstRun() || !await isModelAvailable(config);
|
|
9624
9728
|
if (needsSetup && config.backendType === "ollama") {
|
|
9625
9729
|
const setupModel = await runSetupWizard(config);
|
|
@@ -9652,6 +9756,14 @@ async function startInteractive(config, repoPath) {
|
|
|
9652
9756
|
carouselLines
|
|
9653
9757
|
});
|
|
9654
9758
|
const voiceEngine = new VoiceEngine();
|
|
9759
|
+
if (savedSettings.voice) {
|
|
9760
|
+
voiceEngine.toggle().catch(() => {
|
|
9761
|
+
});
|
|
9762
|
+
if (savedSettings.voiceModel) {
|
|
9763
|
+
voiceEngine.setModel(savedSettings.voiceModel).catch(() => {
|
|
9764
|
+
});
|
|
9765
|
+
}
|
|
9766
|
+
}
|
|
9655
9767
|
let currentConfig = { ...config };
|
|
9656
9768
|
let activeTask = null;
|
|
9657
9769
|
let messageQueue = [];
|
|
@@ -9668,8 +9780,9 @@ async function startInteractive(config, repoPath) {
|
|
|
9668
9780
|
process.stdout.on("resize", () => {
|
|
9669
9781
|
if (!carouselRetired) {
|
|
9670
9782
|
const termRows = process.stdout.rows ?? 24;
|
|
9671
|
-
|
|
9672
|
-
process.stdout.write(`\x1B[${
|
|
9783
|
+
const scrollStart = carousel.reservedRows + 1;
|
|
9784
|
+
process.stdout.write(`\x1B[${scrollStart};${termRows}r`);
|
|
9785
|
+
process.stdout.write(`\x1B[${scrollStart};1H\x1B[J`);
|
|
9673
9786
|
renderRichHeader({
|
|
9674
9787
|
model: currentConfig.model,
|
|
9675
9788
|
version,
|
|
@@ -9716,6 +9829,13 @@ async function startInteractive(config, repoPath) {
|
|
|
9716
9829
|
},
|
|
9717
9830
|
async voiceSetModel(id) {
|
|
9718
9831
|
return voiceEngine.setModel(id);
|
|
9832
|
+
},
|
|
9833
|
+
saveSettings(settings) {
|
|
9834
|
+
try {
|
|
9835
|
+
saveProjectSettings(repoRoot, settings);
|
|
9836
|
+
saveGlobalSettings(settings);
|
|
9837
|
+
} catch {
|
|
9838
|
+
}
|
|
9719
9839
|
}
|
|
9720
9840
|
};
|
|
9721
9841
|
showPrompt();
|
|
@@ -10323,7 +10443,7 @@ __export(config_exports, {
|
|
|
10323
10443
|
configCommand: () => configCommand
|
|
10324
10444
|
});
|
|
10325
10445
|
import { join as join19 } from "node:path";
|
|
10326
|
-
import { homedir as
|
|
10446
|
+
import { homedir as homedir7 } from "node:os";
|
|
10327
10447
|
async function configCommand(opts, config) {
|
|
10328
10448
|
if (opts.subCommand === "set") {
|
|
10329
10449
|
return handleSet(opts, config);
|
|
@@ -10345,7 +10465,7 @@ function handleShow(opts, config) {
|
|
|
10345
10465
|
printKeyValue("verbose", String(config.verbose), 2);
|
|
10346
10466
|
printKeyValue("dbPath", config.dbPath, 2);
|
|
10347
10467
|
printSection("Config File");
|
|
10348
|
-
printInfo(`~/.open-agents/config.json (${join19(
|
|
10468
|
+
printInfo(`~/.open-agents/config.json (${join19(homedir7(), ".open-agents", "config.json")})`);
|
|
10349
10469
|
printSection("Environment Variables");
|
|
10350
10470
|
printInfo("OPEN_AGENTS_BACKEND_URL \u2014 override backendUrl");
|
|
10351
10471
|
printInfo("OPEN_AGENTS_MODEL \u2014 override model");
|
package/package.json
CHANGED