@prestyj/boss 4.3.164 → 4.10.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/{chunk-STUHLGRN.js → chunk-72J6ZGVA.js} +13812 -10813
- package/dist/{chunk-STUHLGRN.js.map → chunk-72J6ZGVA.js.map} +1 -1
- package/dist/cli.js +105 -497
- package/dist/cli.js.map +1 -1
- package/dist/{devtools-ASTBUBZC.js → devtools-ORTEPMCM.js} +5 -5
- package/dist/devtools-ORTEPMCM.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/dist/devtools-ASTBUBZC.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createRequire as __createRequire } from "node:module"; const require =
|
|
|
3
3
|
import {
|
|
4
4
|
AnimationProvider,
|
|
5
5
|
AssistantMessage,
|
|
6
|
+
AuthStorage,
|
|
6
7
|
Box_default,
|
|
7
8
|
ChatControls,
|
|
8
9
|
ChatInputStack,
|
|
@@ -10,11 +11,12 @@ import {
|
|
|
10
11
|
ChatLivePane,
|
|
11
12
|
CompactionDone,
|
|
12
13
|
CompactionSpinner,
|
|
13
|
-
|
|
14
|
+
EzBoss,
|
|
14
15
|
InputArea,
|
|
15
16
|
MODELS,
|
|
16
17
|
MessageResponse,
|
|
17
18
|
RESPONSE_LEFT_PADDING,
|
|
19
|
+
TelegramBot,
|
|
18
20
|
TerminalSizeProvider,
|
|
19
21
|
Text,
|
|
20
22
|
ThemeContext,
|
|
@@ -28,17 +30,21 @@ import {
|
|
|
28
30
|
buildToolGroupSummary,
|
|
29
31
|
closeLogger,
|
|
30
32
|
color,
|
|
33
|
+
createAutoUpdater,
|
|
31
34
|
dim,
|
|
32
35
|
formatHistoryWrite,
|
|
33
36
|
getAppPaths,
|
|
34
37
|
getBossState,
|
|
35
38
|
getContextWindow,
|
|
39
|
+
getDefaultModel,
|
|
40
|
+
getModel,
|
|
36
41
|
getNextThinkingLevel,
|
|
37
42
|
getSplashAudioDurationMs,
|
|
38
43
|
getTranscriptItemMarginTop,
|
|
39
44
|
gradientLine,
|
|
40
45
|
indent,
|
|
41
46
|
initLogger,
|
|
47
|
+
isModelLoaded,
|
|
42
48
|
loadSettings,
|
|
43
49
|
loadTheme,
|
|
44
50
|
log,
|
|
@@ -48,6 +54,7 @@ import {
|
|
|
48
54
|
require_react,
|
|
49
55
|
saveSettings,
|
|
50
56
|
serializeCompletedItemToTerminalHistory,
|
|
57
|
+
setProgressCallback,
|
|
51
58
|
setStreamDiagnostic,
|
|
52
59
|
shouldSeparateTranscriptItemKinds,
|
|
53
60
|
shouldTopSpaceStreamingAssistant,
|
|
@@ -56,6 +63,7 @@ import {
|
|
|
56
63
|
subscribeToBossStore,
|
|
57
64
|
tasksStore,
|
|
58
65
|
toolTonePalette,
|
|
66
|
+
transcribeVoice,
|
|
59
67
|
truncatePlain,
|
|
60
68
|
useAnimationActive,
|
|
61
69
|
useAnimationTick,
|
|
@@ -68,7 +76,7 @@ import {
|
|
|
68
76
|
use_input_default,
|
|
69
77
|
use_stdout_default,
|
|
70
78
|
wrapPlain
|
|
71
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-72J6ZGVA.js";
|
|
72
80
|
import "./chunk-7QDS2KEP.js";
|
|
73
81
|
import {
|
|
74
82
|
source_default
|
|
@@ -116,13 +124,13 @@ import readline from "readline";
|
|
|
116
124
|
import os from "os";
|
|
117
125
|
import path2 from "path";
|
|
118
126
|
async function discoverProjects() {
|
|
119
|
-
const [
|
|
120
|
-
|
|
127
|
+
const [ez, cc, cx] = await Promise.all([
|
|
128
|
+
discoverEzcoderProjects(),
|
|
121
129
|
discoverClaudeProjects(),
|
|
122
130
|
discoverCodexProjects()
|
|
123
131
|
]);
|
|
124
132
|
const byPath = /* @__PURE__ */ new Map();
|
|
125
|
-
for (const p of [...
|
|
133
|
+
for (const p of [...ez, ...cc, ...cx]) {
|
|
126
134
|
const existing = byPath.get(p.path);
|
|
127
135
|
if (!existing) {
|
|
128
136
|
byPath.set(p.path, p);
|
|
@@ -153,7 +161,7 @@ function mergeSources(a, b) {
|
|
|
153
161
|
const set = /* @__PURE__ */ new Set([...a, ...b]);
|
|
154
162
|
return Array.from(set).sort((x, y) => SOURCE_ORDER[x] - SOURCE_ORDER[y]);
|
|
155
163
|
}
|
|
156
|
-
async function
|
|
164
|
+
async function discoverEzcoderProjects() {
|
|
157
165
|
const sessionsDir = getAppPaths().sessionsDir;
|
|
158
166
|
let entries;
|
|
159
167
|
try {
|
|
@@ -361,7 +369,7 @@ init_esm_shims();
|
|
|
361
369
|
// package.json
|
|
362
370
|
var package_default = {
|
|
363
371
|
name: "@prestyj/boss",
|
|
364
|
-
version: "4.
|
|
372
|
+
version: "4.10.1",
|
|
365
373
|
type: "module",
|
|
366
374
|
description: "Orchestrator agent that drives multiple ezcoder sessions across projects from a single chat",
|
|
367
375
|
license: "MIT",
|
|
@@ -387,6 +395,7 @@ var package_default = {
|
|
|
387
395
|
devDependencies: {
|
|
388
396
|
"@prestyj/agent": "workspace:*",
|
|
389
397
|
"@prestyj/ai": "workspace:*",
|
|
398
|
+
"@prestyj/core": "workspace:*",
|
|
390
399
|
"@prestyj/cli": "workspace:*",
|
|
391
400
|
"@types/node": "^25.6.0",
|
|
392
401
|
"@types/react": "^19.2.14",
|
|
@@ -517,7 +526,7 @@ var VISIBLE_ROWS = 12;
|
|
|
517
526
|
function sourceBadge(sources) {
|
|
518
527
|
if (sources.length > 1) return { label: "[mix]", color: COLORS.success };
|
|
519
528
|
const only = sources[0];
|
|
520
|
-
if (only === "ezcoder") return { label: "[
|
|
529
|
+
if (only === "ezcoder") return { label: "[ez ]", color: COLORS.accent };
|
|
521
530
|
if (only === "claude-code") return { label: "[cc ]", color: COLORS.warning };
|
|
522
531
|
if (only === "codex") return { label: "[cx ]", color: COLORS.primary };
|
|
523
532
|
return { label: "[?? ]", color: COLORS.textDim };
|
|
@@ -669,317 +678,6 @@ async function runLinkCommand() {
|
|
|
669
678
|
init_esm_shims();
|
|
670
679
|
import path3 from "path";
|
|
671
680
|
import fs3 from "fs/promises";
|
|
672
|
-
|
|
673
|
-
// src/voice-transcriber.ts
|
|
674
|
-
init_esm_shims();
|
|
675
|
-
var TARGET_SAMPLE_RATE = 16e3;
|
|
676
|
-
var MODEL_ID = "Xenova/whisper-tiny.en";
|
|
677
|
-
var transcriber = null;
|
|
678
|
-
var loadPromise = null;
|
|
679
|
-
var onProgress = null;
|
|
680
|
-
function setProgressCallback(cb) {
|
|
681
|
-
onProgress = cb;
|
|
682
|
-
}
|
|
683
|
-
function resample(audio, fromRate, toRate) {
|
|
684
|
-
if (fromRate === toRate) return audio;
|
|
685
|
-
const ratio = fromRate / toRate;
|
|
686
|
-
const newLength = Math.round(audio.length / ratio);
|
|
687
|
-
const result = new Float32Array(newLength);
|
|
688
|
-
for (let i = 0; i < newLength; i++) {
|
|
689
|
-
const srcIndex = i * ratio;
|
|
690
|
-
const low = Math.floor(srcIndex);
|
|
691
|
-
const high = Math.min(low + 1, audio.length - 1);
|
|
692
|
-
const frac = srcIndex - low;
|
|
693
|
-
result[i] = audio[low] * (1 - frac) + audio[high] * frac;
|
|
694
|
-
}
|
|
695
|
-
return result;
|
|
696
|
-
}
|
|
697
|
-
function downmixToMono(channelData) {
|
|
698
|
-
if (channelData.length === 0) return new Float32Array();
|
|
699
|
-
if (channelData.length === 1) return channelData[0];
|
|
700
|
-
const samples = channelData[0].length;
|
|
701
|
-
const out = new Float32Array(samples);
|
|
702
|
-
const scale = 1 / channelData.length;
|
|
703
|
-
for (let i = 0; i < samples; i++) {
|
|
704
|
-
let mixed = 0;
|
|
705
|
-
for (const channel of channelData) mixed += channel[i] ?? 0;
|
|
706
|
-
out[i] = mixed * scale;
|
|
707
|
-
}
|
|
708
|
-
return out;
|
|
709
|
-
}
|
|
710
|
-
async function decodeOggOpus(buffer) {
|
|
711
|
-
const { OggOpusDecoder } = await import("ogg-opus-decoder");
|
|
712
|
-
const decoder = new OggOpusDecoder();
|
|
713
|
-
await decoder.ready;
|
|
714
|
-
try {
|
|
715
|
-
const decoded = await decoder.decodeFile(buffer);
|
|
716
|
-
if (!decoded.channelData?.length || !decoded.channelData[0]?.length) {
|
|
717
|
-
throw new Error("Decoded audio is empty");
|
|
718
|
-
}
|
|
719
|
-
const mono = downmixToMono(decoded.channelData);
|
|
720
|
-
return resample(mono, decoded.sampleRate, TARGET_SAMPLE_RATE);
|
|
721
|
-
} finally {
|
|
722
|
-
decoder.free();
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
async function getTranscriber() {
|
|
726
|
-
if (transcriber) return transcriber;
|
|
727
|
-
if (!loadPromise) {
|
|
728
|
-
loadPromise = (async () => {
|
|
729
|
-
const { pipeline } = await import("@huggingface/transformers");
|
|
730
|
-
const instance = await pipeline("automatic-speech-recognition", MODEL_ID, {
|
|
731
|
-
dtype: "fp32",
|
|
732
|
-
progress_callback: onProgress ?? void 0
|
|
733
|
-
});
|
|
734
|
-
transcriber = instance;
|
|
735
|
-
return instance;
|
|
736
|
-
})();
|
|
737
|
-
}
|
|
738
|
-
return loadPromise;
|
|
739
|
-
}
|
|
740
|
-
function isModelLoaded() {
|
|
741
|
-
return transcriber !== null;
|
|
742
|
-
}
|
|
743
|
-
async function transcribeVoice(fileUrl) {
|
|
744
|
-
const response = await fetch(fileUrl);
|
|
745
|
-
if (!response.ok) throw new Error(`Failed to download voice file: ${response.status}`);
|
|
746
|
-
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
747
|
-
const pcm = await decodeOggOpus(buffer);
|
|
748
|
-
const asr = await getTranscriber();
|
|
749
|
-
const result = await asr(pcm);
|
|
750
|
-
const text = Array.isArray(result) ? result[0]?.text : result.text;
|
|
751
|
-
return (text ?? "").trim();
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// src/telegram.ts
|
|
755
|
-
init_esm_shims();
|
|
756
|
-
var TELEGRAM_API = "https://api.telegram.org";
|
|
757
|
-
var MAX_MESSAGE_LENGTH = 4096;
|
|
758
|
-
var TelegramBot = class {
|
|
759
|
-
token;
|
|
760
|
-
allowedUserId;
|
|
761
|
-
offset = 0;
|
|
762
|
-
running = false;
|
|
763
|
-
onMessage = null;
|
|
764
|
-
onVoiceMessage = null;
|
|
765
|
-
onCallback = null;
|
|
766
|
-
onBotAdded = null;
|
|
767
|
-
onBotRemoved = null;
|
|
768
|
-
constructor(config) {
|
|
769
|
-
this.token = config.botToken;
|
|
770
|
-
this.allowedUserId = config.allowedUserId;
|
|
771
|
-
}
|
|
772
|
-
/** Register handler for incoming text messages. */
|
|
773
|
-
onText(handler) {
|
|
774
|
-
this.onMessage = handler;
|
|
775
|
-
}
|
|
776
|
-
/** Register handler for incoming voice notes. */
|
|
777
|
-
onVoice(handler) {
|
|
778
|
-
this.onVoiceMessage = handler;
|
|
779
|
-
}
|
|
780
|
-
/** Register handler for inline keyboard button presses. */
|
|
781
|
-
onCallbackQuery(handler) {
|
|
782
|
-
this.onCallback = handler;
|
|
783
|
-
}
|
|
784
|
-
/** Register handler for when the bot is added to a group. */
|
|
785
|
-
onAddedToGroup(handler) {
|
|
786
|
-
this.onBotAdded = handler;
|
|
787
|
-
}
|
|
788
|
-
/** Register handler for when the bot is removed from a group. */
|
|
789
|
-
onRemovedFromGroup(handler) {
|
|
790
|
-
this.onBotRemoved = handler;
|
|
791
|
-
}
|
|
792
|
-
/** Start long polling. Blocks until stop() is called. */
|
|
793
|
-
async start() {
|
|
794
|
-
this.running = true;
|
|
795
|
-
const me = await this.apiCall("getMe");
|
|
796
|
-
if (!me.ok) {
|
|
797
|
-
throw new Error(`Invalid bot token: ${JSON.stringify(me)}`);
|
|
798
|
-
}
|
|
799
|
-
while (this.running) {
|
|
800
|
-
try {
|
|
801
|
-
const updates = await this.getUpdates();
|
|
802
|
-
for (const update of updates) {
|
|
803
|
-
await this.handleUpdate(update);
|
|
804
|
-
}
|
|
805
|
-
} catch (err) {
|
|
806
|
-
if (!this.running) break;
|
|
807
|
-
console.error(`[telegram] Poll error: ${err instanceof Error ? err.message : err}`);
|
|
808
|
-
await sleep(3e3);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
/** Stop long polling. */
|
|
813
|
-
stop() {
|
|
814
|
-
this.running = false;
|
|
815
|
-
}
|
|
816
|
-
/** Send a text message to a specific chat. Converts markdown and splits long messages. */
|
|
817
|
-
async send(chatId, text, buttons) {
|
|
818
|
-
const converted = toTelegramMarkdown(text);
|
|
819
|
-
const chunks = splitMessage(converted);
|
|
820
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
821
|
-
const isLast = i === chunks.length - 1;
|
|
822
|
-
const replyMarkup = isLast && buttons ? {
|
|
823
|
-
inline_keyboard: buttons.map(
|
|
824
|
-
(row) => row.map((b) => ({ text: b.text, callback_data: b.callback_data }))
|
|
825
|
-
)
|
|
826
|
-
} : void 0;
|
|
827
|
-
await this.apiCall("sendMessage", {
|
|
828
|
-
chat_id: chatId,
|
|
829
|
-
text: chunks[i],
|
|
830
|
-
parse_mode: "Markdown",
|
|
831
|
-
...replyMarkup ? { reply_markup: replyMarkup } : {}
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
/** Send a plain text message (no markdown parsing) to a specific chat. */
|
|
836
|
-
async sendPlain(chatId, text) {
|
|
837
|
-
const chunks = splitMessage(text);
|
|
838
|
-
for (const chunk of chunks) {
|
|
839
|
-
await this.apiCall("sendMessage", {
|
|
840
|
-
chat_id: chatId,
|
|
841
|
-
text: chunk
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
/** Send a typing indicator to a specific chat. */
|
|
846
|
-
async sendTyping(chatId) {
|
|
847
|
-
await this.apiCall("sendChatAction", {
|
|
848
|
-
chat_id: chatId,
|
|
849
|
-
action: "typing"
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
/** Get a direct download URL for a Telegram file. */
|
|
853
|
-
async getFileUrl(fileId) {
|
|
854
|
-
const result = await this.apiCall("getFile", { file_id: fileId });
|
|
855
|
-
if (!result.ok) throw new Error(`Failed to get file: ${JSON.stringify(result)}`);
|
|
856
|
-
const filePath = result.result.file_path;
|
|
857
|
-
return `${TELEGRAM_API}/file/bot${this.token}/${filePath}`;
|
|
858
|
-
}
|
|
859
|
-
// ── Private ───────────────────────────────────────────
|
|
860
|
-
async getUpdates() {
|
|
861
|
-
const result = await this.apiCall("getUpdates", {
|
|
862
|
-
offset: this.offset,
|
|
863
|
-
timeout: 30,
|
|
864
|
-
allowed_updates: ["message", "callback_query", "my_chat_member"]
|
|
865
|
-
});
|
|
866
|
-
if (!result.ok || !Array.isArray(result.result)) return [];
|
|
867
|
-
const updates = result.result;
|
|
868
|
-
if (updates.length > 0) {
|
|
869
|
-
this.offset = updates[updates.length - 1].update_id + 1;
|
|
870
|
-
}
|
|
871
|
-
return updates;
|
|
872
|
-
}
|
|
873
|
-
async handleUpdate(update) {
|
|
874
|
-
if (update.message) {
|
|
875
|
-
const msg = update.message;
|
|
876
|
-
if (msg.from.id !== this.allowedUserId) {
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
if (msg.text && this.onMessage) {
|
|
880
|
-
this.onMessage({
|
|
881
|
-
text: msg.text,
|
|
882
|
-
chatId: msg.chat.id,
|
|
883
|
-
chatType: msg.chat.type,
|
|
884
|
-
chatTitle: msg.chat.title
|
|
885
|
-
});
|
|
886
|
-
} else if (msg.voice && this.onVoiceMessage) {
|
|
887
|
-
this.onVoiceMessage({
|
|
888
|
-
fileId: msg.voice.file_id,
|
|
889
|
-
duration: msg.voice.duration,
|
|
890
|
-
chatId: msg.chat.id,
|
|
891
|
-
chatType: msg.chat.type,
|
|
892
|
-
chatTitle: msg.chat.title
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
if (update.my_chat_member) {
|
|
897
|
-
const member = update.my_chat_member;
|
|
898
|
-
const status = member.new_chat_member.status;
|
|
899
|
-
if ((status === "member" || status === "administrator") && this.onBotAdded) {
|
|
900
|
-
this.onBotAdded(member.chat.id, member.chat.title);
|
|
901
|
-
} else if ((status === "left" || status === "kicked") && this.onBotRemoved) {
|
|
902
|
-
this.onBotRemoved(member.chat.id);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
if (update.callback_query) {
|
|
906
|
-
const cb = update.callback_query;
|
|
907
|
-
if (cb.from.id !== this.allowedUserId) return;
|
|
908
|
-
await this.apiCall("answerCallbackQuery", { callback_query_id: cb.id });
|
|
909
|
-
if (cb.data && this.onCallback) {
|
|
910
|
-
this.onCallback(cb.data, cb.message.chat.id);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
async apiCall(method, body) {
|
|
915
|
-
const url = `${TELEGRAM_API}/bot${this.token}/${method}`;
|
|
916
|
-
const response = await fetch(url, {
|
|
917
|
-
method: "POST",
|
|
918
|
-
headers: { "Content-Type": "application/json" },
|
|
919
|
-
body: body ? JSON.stringify(body) : void 0
|
|
920
|
-
});
|
|
921
|
-
if (!response.ok) {
|
|
922
|
-
return { ok: false };
|
|
923
|
-
}
|
|
924
|
-
return response.json();
|
|
925
|
-
}
|
|
926
|
-
};
|
|
927
|
-
function toTelegramMarkdown(text) {
|
|
928
|
-
const lines = text.split("\n");
|
|
929
|
-
const result = [];
|
|
930
|
-
let inCodeBlock = false;
|
|
931
|
-
for (const line of lines) {
|
|
932
|
-
if (line.trimStart().startsWith("```")) {
|
|
933
|
-
inCodeBlock = !inCodeBlock;
|
|
934
|
-
result.push(line);
|
|
935
|
-
continue;
|
|
936
|
-
}
|
|
937
|
-
if (inCodeBlock) {
|
|
938
|
-
result.push(line);
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
let transformed = line;
|
|
942
|
-
const headingMatch = transformed.match(/^(#{1,6})\s+(.+)$/);
|
|
943
|
-
if (headingMatch) {
|
|
944
|
-
transformed = `*${headingMatch[2]}*`;
|
|
945
|
-
result.push(transformed);
|
|
946
|
-
continue;
|
|
947
|
-
}
|
|
948
|
-
if (/^(-{3,}|_{3,}|\*{3,})$/.test(transformed.trim())) {
|
|
949
|
-
result.push("");
|
|
950
|
-
continue;
|
|
951
|
-
}
|
|
952
|
-
transformed = transformed.replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
953
|
-
result.push(transformed);
|
|
954
|
-
}
|
|
955
|
-
return result.join("\n");
|
|
956
|
-
}
|
|
957
|
-
function splitMessage(text) {
|
|
958
|
-
if (text.length <= MAX_MESSAGE_LENGTH) return [text];
|
|
959
|
-
const chunks = [];
|
|
960
|
-
let remaining = text;
|
|
961
|
-
while (remaining.length > 0) {
|
|
962
|
-
if (remaining.length <= MAX_MESSAGE_LENGTH) {
|
|
963
|
-
chunks.push(remaining);
|
|
964
|
-
break;
|
|
965
|
-
}
|
|
966
|
-
let splitAt = remaining.lastIndexOf("\n", MAX_MESSAGE_LENGTH);
|
|
967
|
-
if (splitAt === -1 || splitAt < MAX_MESSAGE_LENGTH * 0.5) {
|
|
968
|
-
splitAt = remaining.lastIndexOf(" ", MAX_MESSAGE_LENGTH);
|
|
969
|
-
}
|
|
970
|
-
if (splitAt === -1 || splitAt < MAX_MESSAGE_LENGTH * 0.5) {
|
|
971
|
-
splitAt = MAX_MESSAGE_LENGTH;
|
|
972
|
-
}
|
|
973
|
-
chunks.push(remaining.slice(0, splitAt));
|
|
974
|
-
remaining = remaining.slice(splitAt).trimStart();
|
|
975
|
-
}
|
|
976
|
-
return chunks;
|
|
977
|
-
}
|
|
978
|
-
function sleep(ms) {
|
|
979
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// src/serve-mode.ts
|
|
983
681
|
function getTelegramConfigPath() {
|
|
984
682
|
return path3.join(getAppPaths().agentDir, "boss", "telegram.json");
|
|
985
683
|
}
|
|
@@ -1069,7 +767,7 @@ async function runBossServeMode(options) {
|
|
|
1069
767
|
botToken: options.telegram.botToken,
|
|
1070
768
|
allowedUserId: options.telegram.userId
|
|
1071
769
|
});
|
|
1072
|
-
const boss = new
|
|
770
|
+
const boss = new EzBoss({
|
|
1073
771
|
bossProvider: options.bossProvider,
|
|
1074
772
|
bossModel: options.bossModel,
|
|
1075
773
|
bossThinkingLevel: options.bossThinkingLevel,
|
|
@@ -1641,6 +1339,8 @@ var PARTIAL_BLOCKS = [" ", "\u258F", "\u258E", "\u258D", "\u258C", "\u258B", "\u
|
|
|
1641
1339
|
var LIGHT_SHADE = "\u2591";
|
|
1642
1340
|
var BAR_WIDTH = 8;
|
|
1643
1341
|
var SHORT_MODELS = {
|
|
1342
|
+
"claude-fable-5": "Fable",
|
|
1343
|
+
"claude-mythos-5": "Mythos",
|
|
1644
1344
|
"claude-opus-4-8": "Opus",
|
|
1645
1345
|
"claude-sonnet-4-6": "Sonnet",
|
|
1646
1346
|
"claude-haiku-4-5": "Haiku",
|
|
@@ -2320,7 +2020,7 @@ function tryPlayOnWindowsHost(station) {
|
|
|
2320
2020
|
"Add-Type -AssemblyName presentationCore;",
|
|
2321
2021
|
"Add-Type -AssemblyName WindowsBase;",
|
|
2322
2022
|
"$p = New-Object System.Windows.Media.MediaPlayer;",
|
|
2323
|
-
"$p.Open([uri]$env:
|
|
2023
|
+
"$p.Open([uri]$env:EZBOSS_RADIO_URL);",
|
|
2324
2024
|
"$p.Play();",
|
|
2325
2025
|
"[System.Windows.Threading.Dispatcher]::Run();"
|
|
2326
2026
|
].join(" ");
|
|
@@ -2333,8 +2033,8 @@ function tryPlayOnWindowsHost(station) {
|
|
|
2333
2033
|
stdio: "ignore",
|
|
2334
2034
|
env: {
|
|
2335
2035
|
...process.env,
|
|
2336
|
-
|
|
2337
|
-
WSLENV: (process.env.WSLENV ? process.env.WSLENV + ":" : "") + "
|
|
2036
|
+
EZBOSS_RADIO_URL: station.url,
|
|
2037
|
+
WSLENV: (process.env.WSLENV ? process.env.WSLENV + ":" : "") + "EZBOSS_RADIO_URL"
|
|
2338
2038
|
}
|
|
2339
2039
|
}
|
|
2340
2040
|
);
|
|
@@ -3066,7 +2766,7 @@ function serializeBossItemToTerminalHistory(item, context) {
|
|
|
3066
2766
|
case "update_notice":
|
|
3067
2767
|
return renderUpdateNotice(item, context);
|
|
3068
2768
|
default:
|
|
3069
|
-
return serializeCompletedItemToTerminalHistory(
|
|
2769
|
+
return serializeCompletedItemToTerminalHistory(toEzCoderCompletedItem(item), context);
|
|
3070
2770
|
}
|
|
3071
2771
|
}
|
|
3072
2772
|
function renderBanner(context) {
|
|
@@ -3153,7 +2853,7 @@ function renderTaskDispatch(item, context) {
|
|
|
3153
2853
|
}
|
|
3154
2854
|
return lines.join("\n");
|
|
3155
2855
|
}
|
|
3156
|
-
function
|
|
2856
|
+
function toEzCoderCompletedItem(item) {
|
|
3157
2857
|
switch (item.kind) {
|
|
3158
2858
|
case "user":
|
|
3159
2859
|
return { kind: "user", id: item.id, text: item.text };
|
|
@@ -3311,170 +3011,17 @@ function renderRoundNoticeBox(lines, context, borderColor) {
|
|
|
3311
3011
|
|
|
3312
3012
|
// src/auto-update.ts
|
|
3313
3013
|
init_esm_shims();
|
|
3314
|
-
import { spawn as spawn2 } from "child_process";
|
|
3315
|
-
import fs4 from "fs";
|
|
3316
3014
|
import path4 from "path";
|
|
3317
3015
|
import os2 from "os";
|
|
3318
|
-
var
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
const raw = fs4.readFileSync(getStateFilePath(), "utf-8");
|
|
3328
|
-
return JSON.parse(raw);
|
|
3329
|
-
} catch {
|
|
3330
|
-
return null;
|
|
3331
|
-
}
|
|
3332
|
-
}
|
|
3333
|
-
function writeState(state) {
|
|
3334
|
-
try {
|
|
3335
|
-
const dir = path4.dirname(getStateFilePath());
|
|
3336
|
-
fs4.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3337
|
-
fs4.writeFileSync(getStateFilePath(), JSON.stringify(state));
|
|
3338
|
-
} catch {
|
|
3339
|
-
}
|
|
3340
|
-
}
|
|
3341
|
-
function compareVersions(a, b) {
|
|
3342
|
-
const pa = a.split(".").map(Number);
|
|
3343
|
-
const pb = b.split(".").map(Number);
|
|
3344
|
-
for (let i = 0; i < 3; i++) {
|
|
3345
|
-
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
3346
|
-
if (diff !== 0) return diff;
|
|
3347
|
-
}
|
|
3348
|
-
return 0;
|
|
3349
|
-
}
|
|
3350
|
-
function detectInstallInfo() {
|
|
3351
|
-
const scriptPath = (process.argv[1] ?? "").replace(/\\/g, "/");
|
|
3352
|
-
if (scriptPath.includes("/_npx/")) {
|
|
3353
|
-
return { packageManager: "unknown" /* UNKNOWN */, updateCommand: null };
|
|
3354
|
-
}
|
|
3355
|
-
if (scriptPath.includes("/.pnpm") || scriptPath.includes("/pnpm/global")) {
|
|
3356
|
-
return {
|
|
3357
|
-
packageManager: "pnpm" /* PNPM */,
|
|
3358
|
-
updateCommand: `pnpm add -g ${PACKAGE_NAME}@latest`
|
|
3359
|
-
};
|
|
3360
|
-
}
|
|
3361
|
-
if (scriptPath.includes("/.yarn/") || scriptPath.includes("/yarn/global")) {
|
|
3362
|
-
return {
|
|
3363
|
-
packageManager: "yarn" /* YARN */,
|
|
3364
|
-
updateCommand: `yarn global add ${PACKAGE_NAME}@latest`
|
|
3365
|
-
};
|
|
3366
|
-
}
|
|
3367
|
-
return {
|
|
3368
|
-
packageManager: "npm" /* NPM */,
|
|
3369
|
-
updateCommand: `npm install -g ${PACKAGE_NAME}@latest`
|
|
3370
|
-
};
|
|
3371
|
-
}
|
|
3372
|
-
async function fetchLatestVersion() {
|
|
3373
|
-
try {
|
|
3374
|
-
const controller = new AbortController();
|
|
3375
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
3376
|
-
const response = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
3377
|
-
clearTimeout(timeout);
|
|
3378
|
-
const data = await response.json();
|
|
3379
|
-
const version = data.version?.trim();
|
|
3380
|
-
return version && /^\d+\.\d+\.\d+/.test(version) ? version : null;
|
|
3381
|
-
} catch {
|
|
3382
|
-
return null;
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
function performUpdateInBackground(command) {
|
|
3386
|
-
try {
|
|
3387
|
-
const parts = command.split(" ");
|
|
3388
|
-
const child = spawn2(parts[0], parts.slice(1), {
|
|
3389
|
-
detached: true,
|
|
3390
|
-
stdio: "ignore",
|
|
3391
|
-
env: { ...process.env, npm_config_loglevel: "silent" }
|
|
3392
|
-
});
|
|
3393
|
-
child.unref();
|
|
3394
|
-
} catch {
|
|
3395
|
-
}
|
|
3396
|
-
}
|
|
3397
|
-
function checkAndAutoUpdate(currentVersion) {
|
|
3398
|
-
try {
|
|
3399
|
-
const state = readState();
|
|
3400
|
-
let message = null;
|
|
3401
|
-
if (state?.updatePending && state.latestVersion) {
|
|
3402
|
-
if (compareVersions(state.latestVersion, currentVersion) > 0) {
|
|
3403
|
-
const info = detectInstallInfo();
|
|
3404
|
-
if (info.updateCommand) {
|
|
3405
|
-
performUpdateInBackground(info.updateCommand);
|
|
3406
|
-
message = `Ken just shipped ${state.latestVersion}! Installing in the background \u2014 takes effect next launch.`;
|
|
3407
|
-
writeState({
|
|
3408
|
-
...state,
|
|
3409
|
-
lastCheckedAt: Date.now(),
|
|
3410
|
-
updatePending: false,
|
|
3411
|
-
lastUpdateAttempt: Date.now()
|
|
3412
|
-
});
|
|
3413
|
-
}
|
|
3414
|
-
} else {
|
|
3415
|
-
writeState({ ...state, updatePending: false });
|
|
3416
|
-
}
|
|
3417
|
-
}
|
|
3418
|
-
const shouldCheck = !state || Date.now() - state.lastCheckedAt > CHECK_INTERVAL_MS;
|
|
3419
|
-
if (shouldCheck) scheduleBackgroundCheck(currentVersion);
|
|
3420
|
-
return message;
|
|
3421
|
-
} catch {
|
|
3422
|
-
return null;
|
|
3423
|
-
}
|
|
3424
|
-
}
|
|
3425
|
-
function getPendingUpdate(currentVersion) {
|
|
3426
|
-
try {
|
|
3427
|
-
const state = readState();
|
|
3428
|
-
if (!state?.latestVersion) return null;
|
|
3429
|
-
if (compareVersions(state.latestVersion, currentVersion) <= 0) return null;
|
|
3430
|
-
return { latestVersion: state.latestVersion };
|
|
3431
|
-
} catch {
|
|
3432
|
-
return null;
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
|
-
function scheduleBackgroundCheck(currentVersion) {
|
|
3436
|
-
fetchLatestVersion().then((latestVersion) => {
|
|
3437
|
-
const newState = {
|
|
3438
|
-
lastCheckedAt: Date.now(),
|
|
3439
|
-
latestVersion: latestVersion ?? void 0,
|
|
3440
|
-
updatePending: false
|
|
3441
|
-
};
|
|
3442
|
-
if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
|
|
3443
|
-
newState.updatePending = true;
|
|
3444
|
-
}
|
|
3445
|
-
writeState(newState);
|
|
3446
|
-
}).catch(() => {
|
|
3447
|
-
});
|
|
3448
|
-
}
|
|
3449
|
-
var periodicTimer = null;
|
|
3450
|
-
function startPeriodicUpdateCheck(currentVersion, onUpdate) {
|
|
3451
|
-
if (periodicTimer) return;
|
|
3452
|
-
periodicTimer = setInterval(() => {
|
|
3453
|
-
fetchLatestVersion().then((latestVersion) => {
|
|
3454
|
-
if (!latestVersion) return;
|
|
3455
|
-
if (compareVersions(latestVersion, currentVersion) <= 0) return;
|
|
3456
|
-
const info = detectInstallInfo();
|
|
3457
|
-
if (!info.updateCommand) return;
|
|
3458
|
-
writeState({
|
|
3459
|
-
lastCheckedAt: Date.now(),
|
|
3460
|
-
latestVersion,
|
|
3461
|
-
updatePending: true
|
|
3462
|
-
});
|
|
3463
|
-
onUpdate(
|
|
3464
|
-
`Ken just pushed a fresh update \u2014 ${currentVersion} \u2192 ${latestVersion}! Restart ezboss to grab it (or run ${info.updateCommand} if you can't wait).`
|
|
3465
|
-
);
|
|
3466
|
-
stopPeriodicUpdateCheck();
|
|
3467
|
-
}).catch(() => {
|
|
3468
|
-
});
|
|
3469
|
-
}, CHECK_INTERVAL_MS);
|
|
3470
|
-
periodicTimer.unref();
|
|
3471
|
-
}
|
|
3472
|
-
function stopPeriodicUpdateCheck() {
|
|
3473
|
-
if (periodicTimer) {
|
|
3474
|
-
clearInterval(periodicTimer);
|
|
3475
|
-
periodicTimer = null;
|
|
3476
|
-
}
|
|
3477
|
-
}
|
|
3016
|
+
var updater = createAutoUpdater({
|
|
3017
|
+
packageName: "@prestyj/boss",
|
|
3018
|
+
stateFilePath: () => path4.join(os2.homedir(), ".ezcoder", "boss", "update-state.json"),
|
|
3019
|
+
periodicMessage: ({ currentVersion, latestVersion, updateCommand }) => `Ken just pushed a fresh update \u2014 ${currentVersion} \u2192 ${latestVersion}! Restart ezboss to grab it (or run ${updateCommand} if you can't wait).`
|
|
3020
|
+
});
|
|
3021
|
+
var checkAndAutoUpdate = updater.checkAndAutoUpdate;
|
|
3022
|
+
var getPendingUpdate = updater.getPendingUpdate;
|
|
3023
|
+
var startPeriodicUpdateCheck = updater.startPeriodicUpdateCheck;
|
|
3024
|
+
var stopPeriodicUpdateCheck = updater.stopPeriodicUpdateCheck;
|
|
3478
3025
|
|
|
3479
3026
|
// src/orchestrator-app.tsx
|
|
3480
3027
|
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -4098,10 +3645,12 @@ async function runServeSubcommand(argv) {
|
|
|
4098
3645
|
process.exit(1);
|
|
4099
3646
|
}
|
|
4100
3647
|
const settings = await loadSettings();
|
|
4101
|
-
const bossProvider =
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
3648
|
+
const { bossProvider, bossModel, workerProvider, workerModel } = await resolveBossAuth({
|
|
3649
|
+
bossProvider: settings.bossProvider ?? "anthropic",
|
|
3650
|
+
bossModel: cliBossModel ?? settings.bossModel ?? "claude-opus-4-8",
|
|
3651
|
+
workerProvider: settings.workerProvider ?? "anthropic",
|
|
3652
|
+
workerModel: cliWorkerModel ?? settings.workerModel ?? "claude-sonnet-4-6"
|
|
3653
|
+
});
|
|
4105
3654
|
await runBossServeMode({
|
|
4106
3655
|
bossProvider,
|
|
4107
3656
|
bossModel,
|
|
@@ -4111,6 +3660,45 @@ async function runServeSubcommand(argv) {
|
|
|
4111
3660
|
telegram: { botToken, userId }
|
|
4112
3661
|
});
|
|
4113
3662
|
}
|
|
3663
|
+
var ALL_PROVIDERS = [
|
|
3664
|
+
"anthropic",
|
|
3665
|
+
"openai",
|
|
3666
|
+
"xiaomi",
|
|
3667
|
+
"gemini",
|
|
3668
|
+
"glm",
|
|
3669
|
+
"moonshot",
|
|
3670
|
+
"minimax",
|
|
3671
|
+
"deepseek",
|
|
3672
|
+
"openrouter"
|
|
3673
|
+
];
|
|
3674
|
+
function bossDefaultModel(provider) {
|
|
3675
|
+
return provider === "anthropic" ? "claude-opus-4-8" : getDefaultModel(provider).id;
|
|
3676
|
+
}
|
|
3677
|
+
async function resolveBossAuth(input) {
|
|
3678
|
+
const auth = new AuthStorage();
|
|
3679
|
+
await auth.load();
|
|
3680
|
+
const stored = await auth.listProviders();
|
|
3681
|
+
const loggedIn = ALL_PROVIDERS.filter((p) => stored.includes(p));
|
|
3682
|
+
if (loggedIn.length === 0) {
|
|
3683
|
+
throw new Error('Not logged in to any provider. Run "ezcoder login" to authenticate.');
|
|
3684
|
+
}
|
|
3685
|
+
const fallback = loggedIn[0];
|
|
3686
|
+
const resolve = (preferredProvider, preferredModel, defaultFor) => {
|
|
3687
|
+
const provider = loggedIn.includes(preferredProvider) ? preferredProvider : fallback;
|
|
3688
|
+
const modelFits = getModel(preferredModel)?.provider === provider;
|
|
3689
|
+
return { provider, model: modelFits ? preferredModel : defaultFor(provider) };
|
|
3690
|
+
};
|
|
3691
|
+
const boss = resolve(input.bossProvider, input.bossModel, bossDefaultModel);
|
|
3692
|
+
const worker = resolve(input.workerProvider, input.workerModel, (p) => getDefaultModel(p).id);
|
|
3693
|
+
const fellBack = boss.provider !== input.bossProvider || worker.provider !== input.workerProvider;
|
|
3694
|
+
return {
|
|
3695
|
+
bossProvider: boss.provider,
|
|
3696
|
+
bossModel: boss.model,
|
|
3697
|
+
workerProvider: worker.provider,
|
|
3698
|
+
workerModel: worker.model,
|
|
3699
|
+
fellBack
|
|
3700
|
+
};
|
|
3701
|
+
}
|
|
4114
3702
|
async function runOrchestrator(args) {
|
|
4115
3703
|
if (args.projects.length === 0) {
|
|
4116
3704
|
const links = await loadLinks();
|
|
@@ -4127,10 +3715,30 @@ async function runOrchestrator(args) {
|
|
|
4127
3715
|
caption: `Spinning up ${args.projects.length} worker${args.projects.length === 1 ? "" : "s"}\u2026`
|
|
4128
3716
|
});
|
|
4129
3717
|
const settings = await loadSettings();
|
|
4130
|
-
const
|
|
4131
|
-
const
|
|
4132
|
-
const
|
|
4133
|
-
const
|
|
3718
|
+
const preferredBossProvider = args.bossProvider ?? settings.bossProvider ?? "anthropic";
|
|
3719
|
+
const preferredBossModel = args.bossModel ?? settings.bossModel ?? "claude-opus-4-8";
|
|
3720
|
+
const preferredWorkerProvider = args.workerProvider ?? settings.workerProvider ?? "anthropic";
|
|
3721
|
+
const preferredWorkerModel = args.workerModel ?? settings.workerModel ?? "claude-sonnet-4-6";
|
|
3722
|
+
const {
|
|
3723
|
+
bossProvider: finalBossProvider,
|
|
3724
|
+
bossModel: finalBossModel,
|
|
3725
|
+
workerProvider: finalWorkerProvider,
|
|
3726
|
+
workerModel: finalWorkerModel,
|
|
3727
|
+
fellBack
|
|
3728
|
+
} = await resolveBossAuth({
|
|
3729
|
+
bossProvider: preferredBossProvider,
|
|
3730
|
+
bossModel: preferredBossModel,
|
|
3731
|
+
workerProvider: preferredWorkerProvider,
|
|
3732
|
+
workerModel: preferredWorkerModel
|
|
3733
|
+
});
|
|
3734
|
+
if (fellBack) {
|
|
3735
|
+
log("INFO", "cli", "provider fallback", {
|
|
3736
|
+
preferredBoss: preferredBossProvider,
|
|
3737
|
+
boss: finalBossProvider,
|
|
3738
|
+
preferredWorker: preferredWorkerProvider,
|
|
3739
|
+
worker: finalWorkerProvider
|
|
3740
|
+
});
|
|
3741
|
+
}
|
|
4134
3742
|
initLogger({
|
|
4135
3743
|
version: VERSION,
|
|
4136
3744
|
bossProvider: finalBossProvider,
|
|
@@ -4148,7 +3756,7 @@ async function runOrchestrator(args) {
|
|
|
4148
3756
|
});
|
|
4149
3757
|
const updateMessage = checkAndAutoUpdate(VERSION);
|
|
4150
3758
|
if (updateMessage) log("INFO", "auto_update", updateMessage);
|
|
4151
|
-
const boss = new
|
|
3759
|
+
const boss = new EzBoss({
|
|
4152
3760
|
bossProvider: finalBossProvider,
|
|
4153
3761
|
bossModel: finalBossModel,
|
|
4154
3762
|
bossThinkingLevel: settings.bossThinkingLevel,
|
|
@@ -4202,7 +3810,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
4202
3810
|
main().catch((err) => {
|
|
4203
3811
|
const message = err instanceof Error ? err.message : String(err);
|
|
4204
3812
|
process.stderr.write(source_default.hex(COLORS.error)(`
|
|
4205
|
-
|
|
3813
|
+
ez-boss failed: ${message}
|
|
4206
3814
|
`));
|
|
4207
3815
|
process.exit(1);
|
|
4208
3816
|
});
|