codex-channel-bgos 0.2.0
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/LICENSE +21 -0
- package/README.md +114 -0
- package/dist/adapter.d.ts +96 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +677 -0
- package/dist/adapter.js.map +1 -0
- package/dist/agent-hints.d.ts +20 -0
- package/dist/agent-hints.d.ts.map +1 -0
- package/dist/agent-hints.js +92 -0
- package/dist/agent-hints.js.map +1 -0
- package/dist/agent-identity.d.ts +36 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +42 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/attachment-bridge.d.ts +64 -0
- package/dist/attachment-bridge.d.ts.map +1 -0
- package/dist/attachment-bridge.js +216 -0
- package/dist/attachment-bridge.js.map +1 -0
- package/dist/auth-mode.d.ts +34 -0
- package/dist/auth-mode.d.ts.map +1 -0
- package/dist/auth-mode.js +48 -0
- package/dist/auth-mode.js.map +1 -0
- package/dist/bgos-api.d.ts +191 -0
- package/dist/bgos-api.d.ts.map +1 -0
- package/dist/bgos-api.js +225 -0
- package/dist/bgos-api.js.map +1 -0
- package/dist/bgos-ws.d.ts +94 -0
- package/dist/bgos-ws.d.ts.map +1 -0
- package/dist/bgos-ws.js +310 -0
- package/dist/bgos-ws.js.map +1 -0
- package/dist/capabilities.d.ts +28 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +44 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/catalog-sync.d.ts +26 -0
- package/dist/catalog-sync.d.ts.map +1 -0
- package/dist/catalog-sync.js +24 -0
- package/dist/catalog-sync.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +152 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-host.d.ts +44 -0
- package/dist/codex-host.d.ts.map +1 -0
- package/dist/codex-host.js +142 -0
- package/dist/codex-host.js.map +1 -0
- package/dist/commands-sync.d.ts +24 -0
- package/dist/commands-sync.d.ts.map +1 -0
- package/dist/commands-sync.js +43 -0
- package/dist/commands-sync.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/default-commands.d.ts +27 -0
- package/dist/default-commands.d.ts.map +1 -0
- package/dist/default-commands.js +64 -0
- package/dist/default-commands.js.map +1 -0
- package/dist/event-mapper.d.ts +43 -0
- package/dist/event-mapper.d.ts.map +1 -0
- package/dist/event-mapper.js +127 -0
- package/dist/event-mapper.js.map +1 -0
- package/dist/heartbeat.d.ts +75 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +186 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/inbound-handler.d.ts +167 -0
- package/dist/inbound-handler.d.ts.map +1 -0
- package/dist/inbound-handler.js +282 -0
- package/dist/inbound-handler.js.map +1 -0
- package/dist/inbound-input.d.ts +17 -0
- package/dist/inbound-input.d.ts.map +1 -0
- package/dist/inbound-input.js +25 -0
- package/dist/inbound-input.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/install-service.d.ts +8 -0
- package/dist/install-service.d.ts.map +1 -0
- package/dist/install-service.js +66 -0
- package/dist/install-service.js.map +1 -0
- package/dist/last-id-store.d.ts +33 -0
- package/dist/last-id-store.d.ts.map +1 -0
- package/dist/last-id-store.js +101 -0
- package/dist/last-id-store.js.map +1 -0
- package/dist/load-config.d.ts +30 -0
- package/dist/load-config.d.ts.map +1 -0
- package/dist/load-config.js +86 -0
- package/dist/load-config.js.map +1 -0
- package/dist/media-classify.d.ts +37 -0
- package/dist/media-classify.d.ts.map +1 -0
- package/dist/media-classify.js +108 -0
- package/dist/media-classify.js.map +1 -0
- package/dist/media-guard.d.ts +13 -0
- package/dist/media-guard.d.ts.map +1 -0
- package/dist/media-guard.js +159 -0
- package/dist/media-guard.js.map +1 -0
- package/dist/outbound-retry.d.ts +24 -0
- package/dist/outbound-retry.d.ts.map +1 -0
- package/dist/outbound-retry.js +75 -0
- package/dist/outbound-retry.js.map +1 -0
- package/dist/outbound.d.ts +223 -0
- package/dist/outbound.d.ts.map +1 -0
- package/dist/outbound.js +366 -0
- package/dist/outbound.js.map +1 -0
- package/dist/outbox.d.ts +16 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +88 -0
- package/dist/outbox.js.map +1 -0
- package/dist/pair-cli.d.ts +44 -0
- package/dist/pair-cli.d.ts.map +1 -0
- package/dist/pair-cli.js +182 -0
- package/dist/pair-cli.js.map +1 -0
- package/dist/pending-unknown-store.d.ts +26 -0
- package/dist/pending-unknown-store.d.ts.map +1 -0
- package/dist/pending-unknown-store.js +135 -0
- package/dist/pending-unknown-store.js.map +1 -0
- package/dist/processed-ids.d.ts +36 -0
- package/dist/processed-ids.d.ts.map +1 -0
- package/dist/processed-ids.js +55 -0
- package/dist/processed-ids.js.map +1 -0
- package/dist/reply-markers.d.ts +42 -0
- package/dist/reply-markers.d.ts.map +1 -0
- package/dist/reply-markers.js +124 -0
- package/dist/reply-markers.js.map +1 -0
- package/dist/setup/supervisor.d.ts +16 -0
- package/dist/setup/supervisor.d.ts.map +1 -0
- package/dist/setup/supervisor.js +61 -0
- package/dist/setup/supervisor.js.map +1 -0
- package/dist/thread-map.d.ts +12 -0
- package/dist/thread-map.d.ts.map +1 -0
- package/dist/thread-map.js +72 -0
- package/dist/thread-map.js.map +1 -0
- package/dist/tool-progress.d.ts +103 -0
- package/dist/tool-progress.d.ts.map +1 -0
- package/dist/tool-progress.js +216 -0
- package/dist/tool-progress.js.map +1 -0
- package/dist/types.d.ts +244 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +28 -0
- package/dist/version.js.map +1 -0
- package/dist/voice-rpc.d.ts +37 -0
- package/dist/voice-rpc.d.ts.map +1 -0
- package/dist/voice-rpc.js +44 -0
- package/dist/voice-rpc.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a Codex text reply for BGOS outbound markers and strip them from the
|
|
3
|
+
* user-visible text. Codex emits a single text stream, so, like OpenClaw, the
|
|
4
|
+
* agent-facing surface uses marker syntax (documented in agent-hints.ts and
|
|
5
|
+
* AGENTS.md):
|
|
6
|
+
*
|
|
7
|
+
* MEDIA:/abs/path one file per line -> outbound files[]
|
|
8
|
+
* STATUS: <text> set the agent status line (empty clears)
|
|
9
|
+
* [[BGOS_BUTTONS]] ... [[/...]] inline option buttons (Label | value, <=6)
|
|
10
|
+
* [[BGOS_ASK]] ... [[/BGOS_ASK]] blocking multi-question modal (<=4 questions)
|
|
11
|
+
*
|
|
12
|
+
* tool_progress is NOT a marker: Codex streams real tool events, so the daemon
|
|
13
|
+
* drives that card from run() events (see event-mapper.ts), not from the reply.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_BUTTONS = 6;
|
|
16
|
+
const MAX_ASK_QUESTIONS = 4;
|
|
17
|
+
const MAX_ASK_OPTIONS = 6;
|
|
18
|
+
const BUTTONS_RE = /\[\[BGOS_BUTTONS\]\]([\s\S]*?)\[\[\/BGOS_BUTTONS\]\]/;
|
|
19
|
+
const ASK_RE = /\[\[BGOS_ASK\]\]([\s\S]*?)\[\[\/BGOS_ASK\]\]/;
|
|
20
|
+
function parseOptionLine(line) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
return null;
|
|
24
|
+
const pipe = trimmed.indexOf("|");
|
|
25
|
+
if (pipe === -1) {
|
|
26
|
+
return { text: trimmed, callbackData: trimmed };
|
|
27
|
+
}
|
|
28
|
+
const text = trimmed.slice(0, pipe).trim();
|
|
29
|
+
const callbackData = trimmed.slice(pipe + 1).trim();
|
|
30
|
+
if (!text)
|
|
31
|
+
return null;
|
|
32
|
+
return { text, callbackData: callbackData || text };
|
|
33
|
+
}
|
|
34
|
+
function parseButtonsBlock(body) {
|
|
35
|
+
const options = [];
|
|
36
|
+
for (const raw of body.split("\n")) {
|
|
37
|
+
const opt = parseOptionLine(raw);
|
|
38
|
+
if (opt)
|
|
39
|
+
options.push(opt);
|
|
40
|
+
if (options.length >= MAX_BUTTONS)
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return options.length > 0 ? { options } : null;
|
|
44
|
+
}
|
|
45
|
+
function parseAskBlock(body) {
|
|
46
|
+
const questions = [];
|
|
47
|
+
let current = null;
|
|
48
|
+
const push = () => {
|
|
49
|
+
if (current && questions.length < MAX_ASK_QUESTIONS)
|
|
50
|
+
questions.push(current);
|
|
51
|
+
};
|
|
52
|
+
for (const raw of body.split("\n")) {
|
|
53
|
+
const line = raw.trim();
|
|
54
|
+
if (!line)
|
|
55
|
+
continue;
|
|
56
|
+
if (line.startsWith("Q:")) {
|
|
57
|
+
push();
|
|
58
|
+
current =
|
|
59
|
+
questions.length < MAX_ASK_QUESTIONS
|
|
60
|
+
? {
|
|
61
|
+
text: line.slice(2).trim(),
|
|
62
|
+
options: [],
|
|
63
|
+
allowFreeText: true,
|
|
64
|
+
allowSkip: true,
|
|
65
|
+
}
|
|
66
|
+
: null;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (!current)
|
|
70
|
+
continue;
|
|
71
|
+
if (line === "noskip") {
|
|
72
|
+
current.allowSkip = false;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (line === "nofreetext") {
|
|
76
|
+
current.allowFreeText = false;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const opt = parseOptionLine(line);
|
|
80
|
+
if (opt && current.options.length < MAX_ASK_OPTIONS)
|
|
81
|
+
current.options.push(opt);
|
|
82
|
+
}
|
|
83
|
+
push();
|
|
84
|
+
return questions.length > 0 ? { questions } : null;
|
|
85
|
+
}
|
|
86
|
+
function collapse(text) {
|
|
87
|
+
return text.replace(/\n{3,}/g, "\n\n").trim();
|
|
88
|
+
}
|
|
89
|
+
export function parseReply(input) {
|
|
90
|
+
let text = input ?? "";
|
|
91
|
+
const buttonsMatch = BUTTONS_RE.exec(text);
|
|
92
|
+
const buttons = buttonsMatch ? parseButtonsBlock(buttonsMatch[1] ?? "") : null;
|
|
93
|
+
if (buttonsMatch)
|
|
94
|
+
text = text.replace(BUTTONS_RE, "");
|
|
95
|
+
const askMatch = ASK_RE.exec(text);
|
|
96
|
+
const ask = askMatch ? parseAskBlock(askMatch[1] ?? "") : null;
|
|
97
|
+
if (askMatch)
|
|
98
|
+
text = text.replace(ASK_RE, "");
|
|
99
|
+
const media = [];
|
|
100
|
+
let status = null;
|
|
101
|
+
const kept = [];
|
|
102
|
+
for (const line of text.split("\n")) {
|
|
103
|
+
const trimmed = line.trim();
|
|
104
|
+
if (trimmed.startsWith("MEDIA:")) {
|
|
105
|
+
const path = trimmed.slice("MEDIA:".length).trim();
|
|
106
|
+
if (path)
|
|
107
|
+
media.push(path);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (trimmed === "STATUS:" || trimmed.startsWith("STATUS:")) {
|
|
111
|
+
status = { text: trimmed.slice("STATUS:".length).trim() };
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
kept.push(line);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
cleanText: collapse(kept.join("\n")),
|
|
118
|
+
media,
|
|
119
|
+
buttons,
|
|
120
|
+
ask,
|
|
121
|
+
status,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=reply-markers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-markers.js","sourceRoot":"","sources":["../src/reply-markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkCH,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,UAAU,GAAG,sDAAsD,CAAC;AAC1E,MAAM,MAAM,GAAG,8CAA8C,CAAC;AAE9D,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,IAAI,IAAI,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,GAAG;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,OAAO,CAAC,MAAM,IAAI,WAAW;YAAE,MAAM;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,IAAI,OAAO,GAAuB,IAAI,CAAC;IAEvC,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,OAAO,IAAI,SAAS,CAAC,MAAM,GAAG,iBAAiB;YAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/E,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,EAAE,CAAC;YACP,OAAO;gBACL,SAAS,CAAC,MAAM,GAAG,iBAAiB;oBAClC,CAAC,CAAC;wBACE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;wBAC1B,OAAO,EAAE,EAAE;wBACX,aAAa,EAAE,IAAI;wBACnB,SAAS,EAAE,IAAI;qBAChB;oBACH,CAAC,CAAC,IAAI,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO,CAAC,aAAa,GAAG,KAAK,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,eAAe;YAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,EAAE,CAAC;IACP,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;IAEvB,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,IAAI,YAAY;QAAE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,IAAI,QAAQ;QAAE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAwB,IAAI,CAAC;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3D,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;QACL,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,KAAK;QACL,OAAO;QACP,GAAG;QACH,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const LAUNCHD_LABEL = "ai.brandgrowthos.codex-bgos";
|
|
2
|
+
export declare const SYSTEMD_UNIT = "codex-bgos.service";
|
|
3
|
+
export type SupervisorKind = "launchd" | "systemd" | "manual";
|
|
4
|
+
export declare function pickSupervisor(platform: string): SupervisorKind;
|
|
5
|
+
export interface SupervisorRenderOptions {
|
|
6
|
+
/** Absolute path to the node binary (process.execPath). */
|
|
7
|
+
nodePath: string;
|
|
8
|
+
/** Absolute path to the daemon CLI entry (dist/cli.js). */
|
|
9
|
+
cliEntry: string;
|
|
10
|
+
/** The CODEX_BGOS_HOME root, for log file placement. */
|
|
11
|
+
home: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function renderLaunchdPlist(opts: SupervisorRenderOptions): string;
|
|
15
|
+
export declare function renderSystemdUnit(opts: SupervisorRenderOptions): string;
|
|
16
|
+
//# sourceMappingURL=supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/setup/supervisor.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,aAAa,gCAAgC,CAAC;AAC3D,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAEjD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAI/D;AAED,MAAM,WAAW,uBAAuB;IACtC,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAyBxE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAgBvE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-supervisor rendering + install for the codex-channel-bgos daemon.
|
|
3
|
+
*
|
|
4
|
+
* The pure render* functions produce a launchd plist (macOS) or systemd user
|
|
5
|
+
* unit (Linux) that runs `node <cli.js> start` and keeps it alive. installService
|
|
6
|
+
* writes and loads the unit; the renderers are unit-tested without touching disk.
|
|
7
|
+
*/
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
export const LAUNCHD_LABEL = "ai.brandgrowthos.codex-bgos";
|
|
10
|
+
export const SYSTEMD_UNIT = "codex-bgos.service";
|
|
11
|
+
export function pickSupervisor(platform) {
|
|
12
|
+
if (platform === "darwin")
|
|
13
|
+
return "launchd";
|
|
14
|
+
if (platform === "linux")
|
|
15
|
+
return "systemd";
|
|
16
|
+
return "manual";
|
|
17
|
+
}
|
|
18
|
+
export function renderLaunchdPlist(opts) {
|
|
19
|
+
const label = opts.label ?? LAUNCHD_LABEL;
|
|
20
|
+
const outLog = join(opts.home, "logs", "codex-bgos.log");
|
|
21
|
+
const errLog = join(opts.home, "logs", "codex-bgos.err");
|
|
22
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
23
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
24
|
+
<plist version="1.0">
|
|
25
|
+
<dict>
|
|
26
|
+
<key>Label</key><string>${label}</string>
|
|
27
|
+
<key>ProgramArguments</key>
|
|
28
|
+
<array>
|
|
29
|
+
<string>${opts.nodePath}</string>
|
|
30
|
+
<string>${opts.cliEntry}</string>
|
|
31
|
+
<string>start</string>
|
|
32
|
+
</array>
|
|
33
|
+
<key>EnvironmentVariables</key><dict>
|
|
34
|
+
<key>NODE_ENV</key><string>production</string>
|
|
35
|
+
</dict>
|
|
36
|
+
<key>StandardOutPath</key><string>${outLog}</string>
|
|
37
|
+
<key>StandardErrorPath</key><string>${errLog}</string>
|
|
38
|
+
<key>RunAtLoad</key><true/>
|
|
39
|
+
<key>KeepAlive</key><true/>
|
|
40
|
+
</dict>
|
|
41
|
+
</plist>
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
export function renderSystemdUnit(opts) {
|
|
45
|
+
return `[Unit]
|
|
46
|
+
Description=codex-channel-bgos daemon (chat with your Codex agents in BGOS)
|
|
47
|
+
After=network-online.target
|
|
48
|
+
Wants=network-online.target
|
|
49
|
+
|
|
50
|
+
[Service]
|
|
51
|
+
Type=simple
|
|
52
|
+
Environment=NODE_ENV=production
|
|
53
|
+
ExecStart=${opts.nodePath} ${opts.cliEntry} start
|
|
54
|
+
Restart=always
|
|
55
|
+
RestartSec=5
|
|
56
|
+
|
|
57
|
+
[Install]
|
|
58
|
+
WantedBy=default.target
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/setup/supervisor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,aAAa,GAAG,6BAA6B,CAAC;AAC3D,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAIjD,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAYD,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzD,OAAO;;;;4BAImB,KAAK;;;cAGnB,IAAI,CAAC,QAAQ;cACb,IAAI,CAAC,QAAQ;;;;;;sCAMW,MAAM;wCACJ,MAAM;;;;;CAK7C,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAA6B;IAC7D,OAAO;;;;;;;;YAQG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;;;;;;CAMzC,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ThreadMap = Record<string, string>;
|
|
2
|
+
/** Path to threads.json; `dir` overrides the home (used in tests). */
|
|
3
|
+
export declare function threadsPath(dir?: string): string;
|
|
4
|
+
/** Load the map from disk. Returns {} on any read/parse error (never throws). */
|
|
5
|
+
export declare function loadThreadMap(path?: string): ThreadMap;
|
|
6
|
+
/** Read the thread id for a chat, or undefined if unmapped. */
|
|
7
|
+
export declare function getThreadId(map: ThreadMap, chatId: string | number): string | undefined;
|
|
8
|
+
/** Set (or overwrite) the thread id for a chat and persist. Mutates `map`. */
|
|
9
|
+
export declare function setThreadId(path: string, map: ThreadMap, chatId: string | number, threadId: string): void;
|
|
10
|
+
/** Drop a chat's thread binding and persist (bridge-local `/new`). Mutates `map`. */
|
|
11
|
+
export declare function resetChat(path: string, map: ThreadMap, chatId: string | number): void;
|
|
12
|
+
//# sourceMappingURL=thread-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-map.d.ts","sourceRoot":"","sources":["../src/thread-map.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAO/C,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAMD,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAsB,GAAG,SAAS,CAarE;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CACzB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,MAAM,GAAG,SAAS,CAEpB;AAcD,8EAA8E;AAC9E,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,EAAE,MAAM,GACf,IAAI,CAGN;AAED,qFAAqF;AACrF,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,IAAI,CAGN"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent map from a BGOS chat id to its Codex thread id.
|
|
3
|
+
*
|
|
4
|
+
* One BGOS chat maps to one long-lived Codex thread: the first user message
|
|
5
|
+
* calls `codex.startThread()`, captures `thread.id` from the `thread.started`
|
|
6
|
+
* event, and stores it here; later messages call `codex.resumeThread(id)` so the
|
|
7
|
+
* conversation keeps its context across daemon restarts (Codex persists the
|
|
8
|
+
* thread body itself under ~/.codex/sessions). The bridge-local `/new` command
|
|
9
|
+
* calls `resetChat` so the next message starts a fresh thread.
|
|
10
|
+
*
|
|
11
|
+
* File: `$CODEX_BGOS_HOME/threads.json` (default `~/.codex-bgos/threads.json`),
|
|
12
|
+
* a flat `{ "<chatId>": "<threadId>" }` object, atomic tmp+rename, mode 0600.
|
|
13
|
+
*/
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { join, dirname } from "node:path";
|
|
16
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
17
|
+
/** Resolve the CODEX_BGOS_HOME root (respects the env override). */
|
|
18
|
+
function codexBgosHome() {
|
|
19
|
+
return process.env.CODEX_BGOS_HOME ?? join(homedir(), ".codex-bgos");
|
|
20
|
+
}
|
|
21
|
+
/** Path to threads.json; `dir` overrides the home (used in tests). */
|
|
22
|
+
export function threadsPath(dir) {
|
|
23
|
+
return join(dir ?? codexBgosHome(), "threads.json");
|
|
24
|
+
}
|
|
25
|
+
function keyOf(chatId) {
|
|
26
|
+
return String(chatId);
|
|
27
|
+
}
|
|
28
|
+
/** Load the map from disk. Returns {} on any read/parse error (never throws). */
|
|
29
|
+
export function loadThreadMap(path = threadsPath()) {
|
|
30
|
+
try {
|
|
31
|
+
const raw = readFileSync(path, "utf8");
|
|
32
|
+
const parsed = JSON.parse(raw);
|
|
33
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
34
|
+
return {};
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
37
|
+
if (typeof v === "string" && v.length > 0)
|
|
38
|
+
out[k] = v;
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Read the thread id for a chat, or undefined if unmapped. */
|
|
47
|
+
export function getThreadId(map, chatId) {
|
|
48
|
+
return map[keyOf(chatId)];
|
|
49
|
+
}
|
|
50
|
+
function persist(path, map) {
|
|
51
|
+
try {
|
|
52
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
53
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
54
|
+
writeFileSync(tmp, JSON.stringify(map, null, 2), { mode: 0o600 });
|
|
55
|
+
renameSync(tmp, path);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// A persistence hiccup must never crash the daemon; the in-memory map still
|
|
59
|
+
// works for the current process, and the next successful write recovers it.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Set (or overwrite) the thread id for a chat and persist. Mutates `map`. */
|
|
63
|
+
export function setThreadId(path, map, chatId, threadId) {
|
|
64
|
+
map[keyOf(chatId)] = threadId;
|
|
65
|
+
persist(path, map);
|
|
66
|
+
}
|
|
67
|
+
/** Drop a chat's thread binding and persist (bridge-local `/new`). Mutates `map`. */
|
|
68
|
+
export function resetChat(path, map, chatId) {
|
|
69
|
+
delete map[keyOf(chatId)];
|
|
70
|
+
persist(path, map);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=thread-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-map.js","sourceRoot":"","sources":["../src/thread-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AAIjB,oEAAoE;AACpE,SAAS,aAAa;IACpB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AACvE,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,IAAI,CAAC,GAAG,IAAI,aAAa,EAAE,EAAE,cAAc,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,KAAK,CAAC,MAAuB;IACpC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,OAAe,WAAW,EAAE;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9E,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;YACvE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CACzB,GAAc,EACd,MAAuB;IAEvB,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,GAAc;IAC3C,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QACzC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,4EAA4E;IAC9E,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,GAAc,EACd,MAAuB,EACvB,QAAgB;IAEhB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,GAAc,EACd,MAAuB;IAEvB,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-progress card lifecycle for Codex.
|
|
3
|
+
*
|
|
4
|
+
* Unlike OpenClaw (which hides tool lifecycle from the channel adapter and
|
|
5
|
+
* relies on a post-hoc agent-emitted marker block), Codex streams Claude's
|
|
6
|
+
* `tool_use` blocks LIVE in `src/lib/claude.ts:391` of the fork via the
|
|
7
|
+
* `onToolStart` hook. The fork wires this hook into our `sendToolStart`
|
|
8
|
+
* method below, so we render REAL live cards - pulsing-dot + auto-collapse
|
|
9
|
+
* at end-of-turn, identical to Hermes's behavior.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle (per chat, per turn):
|
|
12
|
+
*
|
|
13
|
+
* first sendToolStart(toolName)
|
|
14
|
+
* → POST messages { messageType:"tool_progress", toolProgress: {
|
|
15
|
+
* state:"running", tools:[{ icon, name, status:"done" }] } }
|
|
16
|
+
* → store new card id in `cardByChat[chatId]`
|
|
17
|
+
*
|
|
18
|
+
* subsequent sendToolStart(toolName) within the same turn
|
|
19
|
+
* → push entry, debounce ≥600 ms (configurable), PATCH the card
|
|
20
|
+
*
|
|
21
|
+
* finalizeTurn() at end of dispatch
|
|
22
|
+
* → PATCH the card to { state:"done", tools:[...] }
|
|
23
|
+
* → drop `cardByChat[chatId]`
|
|
24
|
+
*
|
|
25
|
+
* "All status fires post-hoc done" is the same simplification Hermes makes:
|
|
26
|
+
* Claude doesn't emit per-tool result events to the streaming pipeline,
|
|
27
|
+
* only the start event. By the time the next tool_use arrives (or the turn
|
|
28
|
+
* ends), the previous tool has obviously settled. State="running" on the
|
|
29
|
+
* top-level card stays accurate while at least one tool's run might still
|
|
30
|
+
* be in flight; finalize flips it.
|
|
31
|
+
*
|
|
32
|
+
* Throttling: each tool fires its own PATCH only after `debounceMs`
|
|
33
|
+
* elapses since the last PATCH for the same chat. Cumulative tool list
|
|
34
|
+
* lives in memory; the PATCH always carries the FULL list (server-side
|
|
35
|
+
* is replace-not-append for `toolProgress.tools`).
|
|
36
|
+
*
|
|
37
|
+
* Best-effort by design: a PATCH failure logs a warning but does not block
|
|
38
|
+
* the agent's actual reply. The state is pruned from `cardByChat` so the
|
|
39
|
+
* next tool starts a fresh card cleanly.
|
|
40
|
+
*/
|
|
41
|
+
import type { BgosApi } from "./bgos-api.js";
|
|
42
|
+
/** Per-tool entry on a tool_progress card. */
|
|
43
|
+
export interface ToolProgressEntry {
|
|
44
|
+
icon: string;
|
|
45
|
+
name: string;
|
|
46
|
+
args?: string;
|
|
47
|
+
status: "running" | "done" | "error";
|
|
48
|
+
}
|
|
49
|
+
export interface ToolProgressOptions {
|
|
50
|
+
/** Minimum delay between PATCHes for the same chat. Default 600 ms -
|
|
51
|
+
* matches Hermes's `_PROGRESS_EDIT_INTERVAL/2` throttle so tightly-
|
|
52
|
+
* packed tools don't slam the backend. */
|
|
53
|
+
debounceMs?: number;
|
|
54
|
+
/** Friendly-name → emoji map override. The default covers Claude Code
|
|
55
|
+
* CLI's canonical tool names (`Bash`, `Read`, `Edit`, …). */
|
|
56
|
+
iconForToolName?: (toolName: string) => string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Per-chat card lifecycle for Codex. Construct one per `BGOSAdapter`
|
|
60
|
+
* (the adapter owns it; the fork interacts via `ReplyHandle.sendToolStart`
|
|
61
|
+
* + `ReplyHandle.finalizeTurn`).
|
|
62
|
+
*/
|
|
63
|
+
export declare class ToolProgressOrchestrator {
|
|
64
|
+
private readonly api;
|
|
65
|
+
private readonly debounceMs;
|
|
66
|
+
private readonly iconForToolName;
|
|
67
|
+
private readonly cardByChat;
|
|
68
|
+
constructor(api: BgosApi, options?: ToolProgressOptions);
|
|
69
|
+
/**
|
|
70
|
+
* Record that a tool just started on the agent's side and surface it
|
|
71
|
+
* to BGOS. First call per chat POSTs a new card; subsequent calls PATCH.
|
|
72
|
+
*
|
|
73
|
+
* `toolName` should be the canonical tool id (`Bash`, `Read`, `Edit`,
|
|
74
|
+
* `Grep`, …) - Codex's `friendlyToolName()` already normalizes this.
|
|
75
|
+
* `args` is an optional short summary (≤120 chars, plugin truncates).
|
|
76
|
+
*/
|
|
77
|
+
sendToolStart(params: {
|
|
78
|
+
assistantId: number;
|
|
79
|
+
chatId: number;
|
|
80
|
+
toolName: string;
|
|
81
|
+
args?: string;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* End-of-turn signal. Flushes any pending PATCH, then PATCHes the card
|
|
85
|
+
* one last time with state="done". Idempotent - no-op when no active
|
|
86
|
+
* card exists for this chat.
|
|
87
|
+
*/
|
|
88
|
+
finalizeTurn(chatId: number): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Disconnect path: cancel pending debounced PATCHes so we don't leak
|
|
91
|
+
* timers across an adapter restart. Does NOT issue final PATCHes - the
|
|
92
|
+
* next adapter boot will see the cards in state="running" until the
|
|
93
|
+
* frontend's derived-done heuristic collapses them (BGOS desktop v2.5.4+).
|
|
94
|
+
*/
|
|
95
|
+
dispose(): void;
|
|
96
|
+
/** Test-only - surface internal state so vitest can assert. */
|
|
97
|
+
get _internal(): {
|
|
98
|
+
activeChats: number[];
|
|
99
|
+
};
|
|
100
|
+
private maybePatchSoon;
|
|
101
|
+
private flush;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=tool-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-progress.d.ts","sourceRoot":"","sources":["../src/tool-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;CACtC;AAaD,MAAM,WAAW,mBAAmB;IAClC;;+CAE2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;kEAC8D;IAC9D,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AAED;;;;GAIG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAC/D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;gBAE/C,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,mBAAwB;IAM3D;;;;;;;OAOG;IACG,aAAa,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDjB;;;;OAIG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjD;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAUf,+DAA+D;IAC/D,IAAI,SAAS,IAAI;QAAE,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE,CAEzC;YAEa,cAAc;YAkBd,KAAK;CAgCpB"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-chat card lifecycle for Codex. Construct one per `BGOSAdapter`
|
|
3
|
+
* (the adapter owns it; the fork interacts via `ReplyHandle.sendToolStart`
|
|
4
|
+
* + `ReplyHandle.finalizeTurn`).
|
|
5
|
+
*/
|
|
6
|
+
export class ToolProgressOrchestrator {
|
|
7
|
+
api;
|
|
8
|
+
debounceMs;
|
|
9
|
+
iconForToolName;
|
|
10
|
+
cardByChat = new Map();
|
|
11
|
+
constructor(api, options = {}) {
|
|
12
|
+
this.api = api;
|
|
13
|
+
this.debounceMs = options.debounceMs ?? 600;
|
|
14
|
+
this.iconForToolName = options.iconForToolName ?? defaultIconForToolName;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Record that a tool just started on the agent's side and surface it
|
|
18
|
+
* to BGOS. First call per chat POSTs a new card; subsequent calls PATCH.
|
|
19
|
+
*
|
|
20
|
+
* `toolName` should be the canonical tool id (`Bash`, `Read`, `Edit`,
|
|
21
|
+
* `Grep`, …) - Codex's `friendlyToolName()` already normalizes this.
|
|
22
|
+
* `args` is an optional short summary (≤120 chars, plugin truncates).
|
|
23
|
+
*/
|
|
24
|
+
async sendToolStart(params) {
|
|
25
|
+
const { assistantId, chatId, toolName, args } = params;
|
|
26
|
+
const entry = {
|
|
27
|
+
icon: this.iconForToolName(toolName),
|
|
28
|
+
name: toolName,
|
|
29
|
+
status: "done", // see lifecycle comment at top - only start events stream
|
|
30
|
+
};
|
|
31
|
+
if (args !== undefined && args.length > 0) {
|
|
32
|
+
entry.args = args.length > 120 ? args.slice(0, 119) + "…" : args;
|
|
33
|
+
}
|
|
34
|
+
const existing = this.cardByChat.get(chatId);
|
|
35
|
+
if (existing) {
|
|
36
|
+
existing.tools.push(entry);
|
|
37
|
+
// Backend caps tools[] at 50 - clip so the PATCH doesn't 400.
|
|
38
|
+
if (existing.tools.length > 50) {
|
|
39
|
+
existing.tools = existing.tools.slice(0, 50);
|
|
40
|
+
}
|
|
41
|
+
await this.maybePatchSoon(chatId);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// First tool of the turn - POST a new card.
|
|
45
|
+
try {
|
|
46
|
+
const created = await this.api.postMessage({
|
|
47
|
+
assistantId,
|
|
48
|
+
chatId,
|
|
49
|
+
sender: "assistant",
|
|
50
|
+
text: buildSummary([entry], false),
|
|
51
|
+
messageType: "tool_progress",
|
|
52
|
+
toolProgress: { state: "running", tools: [entry] },
|
|
53
|
+
});
|
|
54
|
+
this.cardByChat.set(chatId, {
|
|
55
|
+
cardId: created.id,
|
|
56
|
+
tools: [entry],
|
|
57
|
+
lastPatchAt: Date.now(),
|
|
58
|
+
pendingFlush: null,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// POST failed - log + drop. Next tool will retry the POST cleanly.
|
|
63
|
+
// eslint-disable-next-line no-console
|
|
64
|
+
console.warn("[codex-channel-bgos] tool_progress POST failed chat=" +
|
|
65
|
+
chatId +
|
|
66
|
+
" err=" +
|
|
67
|
+
(err instanceof Error ? err.message : String(err)));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* End-of-turn signal. Flushes any pending PATCH, then PATCHes the card
|
|
72
|
+
* one last time with state="done". Idempotent - no-op when no active
|
|
73
|
+
* card exists for this chat.
|
|
74
|
+
*/
|
|
75
|
+
async finalizeTurn(chatId) {
|
|
76
|
+
const state = this.cardByChat.get(chatId);
|
|
77
|
+
if (!state)
|
|
78
|
+
return;
|
|
79
|
+
// Clear pending flush - we're about to send the final PATCH ourselves.
|
|
80
|
+
if (state.pendingFlush) {
|
|
81
|
+
clearTimeout(state.pendingFlush);
|
|
82
|
+
state.pendingFlush = null;
|
|
83
|
+
}
|
|
84
|
+
this.cardByChat.delete(chatId);
|
|
85
|
+
try {
|
|
86
|
+
await this.api.patchMessage(state.cardId, {
|
|
87
|
+
text: buildSummary(state.tools, true),
|
|
88
|
+
toolProgress: { state: "done", tools: state.tools },
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
// eslint-disable-next-line no-console
|
|
93
|
+
console.warn("[codex-channel-bgos] tool_progress finalize PATCH failed chat=" +
|
|
94
|
+
chatId +
|
|
95
|
+
" card=" +
|
|
96
|
+
state.cardId +
|
|
97
|
+
" err=" +
|
|
98
|
+
(err instanceof Error ? err.message : String(err)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Disconnect path: cancel pending debounced PATCHes so we don't leak
|
|
103
|
+
* timers across an adapter restart. Does NOT issue final PATCHes - the
|
|
104
|
+
* next adapter boot will see the cards in state="running" until the
|
|
105
|
+
* frontend's derived-done heuristic collapses them (BGOS desktop v2.5.4+).
|
|
106
|
+
*/
|
|
107
|
+
dispose() {
|
|
108
|
+
for (const [, state] of this.cardByChat) {
|
|
109
|
+
if (state.pendingFlush) {
|
|
110
|
+
clearTimeout(state.pendingFlush);
|
|
111
|
+
state.pendingFlush = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this.cardByChat.clear();
|
|
115
|
+
}
|
|
116
|
+
/** Test-only - surface internal state so vitest can assert. */
|
|
117
|
+
get _internal() {
|
|
118
|
+
return { activeChats: Array.from(this.cardByChat.keys()) };
|
|
119
|
+
}
|
|
120
|
+
async maybePatchSoon(chatId) {
|
|
121
|
+
const state = this.cardByChat.get(chatId);
|
|
122
|
+
if (!state)
|
|
123
|
+
return;
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
const elapsed = now - state.lastPatchAt;
|
|
126
|
+
if (elapsed >= this.debounceMs) {
|
|
127
|
+
await this.flush(chatId);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// Within debounce window - schedule a single deferred flush. Repeat
|
|
131
|
+
// calls within the window coalesce (later writes supersede earlier
|
|
132
|
+
// ones because we always send the FULL tool list).
|
|
133
|
+
if (state.pendingFlush)
|
|
134
|
+
return;
|
|
135
|
+
state.pendingFlush = setTimeout(() => {
|
|
136
|
+
void this.flush(chatId);
|
|
137
|
+
}, this.debounceMs - elapsed);
|
|
138
|
+
}
|
|
139
|
+
async flush(chatId) {
|
|
140
|
+
const state = this.cardByChat.get(chatId);
|
|
141
|
+
if (!state)
|
|
142
|
+
return;
|
|
143
|
+
if (state.pendingFlush) {
|
|
144
|
+
clearTimeout(state.pendingFlush);
|
|
145
|
+
state.pendingFlush = null;
|
|
146
|
+
}
|
|
147
|
+
state.lastPatchAt = Date.now();
|
|
148
|
+
try {
|
|
149
|
+
await this.api.patchMessage(state.cardId, {
|
|
150
|
+
text: buildSummary(state.tools, false),
|
|
151
|
+
toolProgress: { state: "running", tools: state.tools },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
// Card may have been deleted upstream - drop our tracking so the
|
|
156
|
+
// next tool starts cleanly via POST. Anything else is just a flaky
|
|
157
|
+
// PATCH; we'll retry on the next tool.
|
|
158
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
159
|
+
if (/404|not found/i.test(msg)) {
|
|
160
|
+
this.cardByChat.delete(chatId);
|
|
161
|
+
}
|
|
162
|
+
// eslint-disable-next-line no-console
|
|
163
|
+
console.warn("[codex-channel-bgos] tool_progress PATCH failed chat=" +
|
|
164
|
+
chatId +
|
|
165
|
+
" card=" +
|
|
166
|
+
state.cardId +
|
|
167
|
+
" err=" +
|
|
168
|
+
msg);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function buildSummary(tools, done) {
|
|
173
|
+
if (tools.length === 0) {
|
|
174
|
+
return done ? "No tools used" : "Working…";
|
|
175
|
+
}
|
|
176
|
+
const names = tools.slice(0, 4).map((t) => t.name);
|
|
177
|
+
const tail = tools.length > 4 ? `, +${tools.length - 4} more` : "";
|
|
178
|
+
if (done) {
|
|
179
|
+
const noun = tools.length === 1 ? "tool" : "tools";
|
|
180
|
+
return `Used ${tools.length} ${noun} · ${names.join(", ")}${tail}`;
|
|
181
|
+
}
|
|
182
|
+
return `Working… · ${names.join(", ")}${tail}`;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Default emoji mapper. Mirrors Hermes's per-tool icons + Codex's own
|
|
186
|
+
* Telegram progress format. Lowercase comparison covers Claude Code CLI's
|
|
187
|
+
* `Bash`/`Read`/`Edit`/`Grep`/… as well as the friendlyToolName variants
|
|
188
|
+
* the fork passes through.
|
|
189
|
+
*/
|
|
190
|
+
function defaultIconForToolName(toolName) {
|
|
191
|
+
const t = toolName.toLowerCase();
|
|
192
|
+
if (t === "bash" || t === "terminal" || t.startsWith("exec"))
|
|
193
|
+
return "💻";
|
|
194
|
+
if (t === "read" || t === "read_file" || t.startsWith("read"))
|
|
195
|
+
return "📖";
|
|
196
|
+
if (t === "edit" || t === "write" || t === "write_file")
|
|
197
|
+
return "📝";
|
|
198
|
+
if (t === "grep" || t === "search" || t.startsWith("search"))
|
|
199
|
+
return "🔎";
|
|
200
|
+
if (t === "glob" || t === "find" || t === "ls" || t.startsWith("list"))
|
|
201
|
+
return "📂";
|
|
202
|
+
if (t === "fetch" || t === "web_fetch" || t === "curl")
|
|
203
|
+
return "🌐";
|
|
204
|
+
if (t === "task" || t === "todowrite" || t === "todo_write")
|
|
205
|
+
return "✅";
|
|
206
|
+
if (t.includes("test"))
|
|
207
|
+
return "🧪";
|
|
208
|
+
if (t.includes("install") || t.includes("npm") || t.includes("pip"))
|
|
209
|
+
return "📦";
|
|
210
|
+
if (t.includes("db") || t.includes("sql") || t.includes("psql"))
|
|
211
|
+
return "🗃️";
|
|
212
|
+
// Sensible default - a single-character glyph the frontend can render
|
|
213
|
+
// in the card's icon slot without breaking layout.
|
|
214
|
+
return "🔧";
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=tool-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-progress.js","sourceRoot":"","sources":["../src/tool-progress.ts"],"names":[],"mappings":"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"}
|