vibeostheog 0.23.42 → 0.23.43

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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.23.43
2
+ - fix: support desktop footer alert chain
3
+
4
+
1
5
  ## 0.23.42
2
6
  Fix paused build followup recovery
3
7
  Fix stuck startup plan restore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.23.42",
3
+ "version": "0.23.43",
4
4
  "description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
5
5
  "scripts": {
6
6
  "release": "node scripts/release.mjs",
@@ -168,21 +168,27 @@ async function _appendFooter(input, output, directory) {
168
168
  output?.messageId ||
169
169
  output?.message?.id ||
170
170
  null;
171
- if (messageID && textCompletePainted.has(messageID))
172
- return;
173
- function _extractText(obj) {
174
- if (typeof obj?.text === "string")
175
- return obj.text;
176
- if (typeof obj?.result === "string")
177
- return obj.result;
178
- if (typeof obj?.content === "string")
179
- return obj.content;
180
- if (Array.isArray(obj?.content))
181
- return obj.content.filter(p => p?.type === "text").map(p => p.text).filter(Boolean).join("\n");
182
- if (Array.isArray(obj?.parts))
183
- return obj.parts.filter(p => p?.type === "text").map(p => p.text).filter(Boolean).join("\n");
184
- return "";
185
- }
171
+ if (messageID && textCompletePainted.has(messageID))
172
+ return;
173
+ function _payload(obj) {
174
+ if (obj?.message && typeof obj.message === "object")
175
+ return obj.message;
176
+ return obj;
177
+ }
178
+ function _extractText(obj) {
179
+ const payload = _payload(obj);
180
+ if (typeof payload?.text === "string")
181
+ return payload.text;
182
+ if (typeof payload?.result === "string")
183
+ return payload.result;
184
+ if (typeof payload?.content === "string")
185
+ return payload.content;
186
+ if (Array.isArray(payload?.content))
187
+ return payload.content.filter(p => p?.type === "text").map(p => p.text).filter(Boolean).join("\n");
188
+ if (Array.isArray(payload?.parts))
189
+ return payload.parts.filter(p => p?.type === "text").map(p => p.text).filter(Boolean).join("\n");
190
+ return "";
191
+ }
186
192
  const text = _extractText(output);
187
193
  if (!text)
188
194
  return;
@@ -330,31 +336,32 @@ async function _appendFooter(input, output, directory) {
330
336
  }
331
337
  }
332
338
  catch { }
339
+ }
340
+ function _setFooter(obj, text) {
341
+ const target = _payload(obj);
342
+ if (typeof target?.text === "string")
343
+ target.text = text;
344
+ else if (typeof target?.result === "string")
345
+ target.result = text;
346
+ else if (typeof target?.content === "string")
347
+ target.content = text;
348
+ else if (Array.isArray(target?.content)) {
349
+ const textParts = target.content.filter(p => p?.type === "text");
350
+ if (textParts.length > 0)
351
+ textParts[textParts.length - 1].text = text;
352
+ else
353
+ target.content.push({ type: "text", text });
333
354
  }
334
- function _setFooter(obj, text) {
335
- if (typeof obj?.text === "string")
336
- obj.text = text;
337
- else if (typeof obj?.result === "string")
338
- obj.result = text;
339
- else if (typeof obj?.content === "string")
340
- obj.content = text;
341
- else if (Array.isArray(obj?.content)) {
342
- const textParts = obj.content.filter(p => p?.type === "text");
343
- if (textParts.length > 0)
344
- textParts[textParts.length - 1].text = text;
345
- else
346
- obj.content.push({ type: "text", text });
347
- }
348
- else if (Array.isArray(obj?.parts)) {
349
- const textParts = obj.parts.filter(p => p?.type === "text");
350
- if (textParts.length > 0)
351
- textParts[textParts.length - 1].text = text;
352
- else
353
- obj.parts.push({ type: "text", text });
354
- }
355
+ else if (Array.isArray(target?.parts)) {
356
+ const textParts = target.parts.filter(p => p?.type === "text");
357
+ if (textParts.length > 0)
358
+ textParts[textParts.length - 1].text = text;
355
359
  else
356
- obj.text = text;
360
+ target.parts.push({ type: "text", text });
357
361
  }
362
+ else
363
+ target.text = text;
364
+ }
358
365
  _setFooter(output, footerText);
359
366
  _lastStrippedText = stripped;
360
367
  // CLI/pipe mode: stdout is already rendered, write footer to stderr
@@ -750,17 +750,21 @@ export const onToolExecuteAfter = async (input, output) => {
750
750
  _footerText += ` | $${formatUsd(ltTotal)}`;
751
751
  }
752
752
  _footerText += ` | ${vibeBrand}${flashIcon} —\n\n`;
753
+ const footerTarget = _payload(output);
753
754
  output.title = _footerText.trim();
754
- if (typeof output?.output === "string")
755
- output.output = _footerText + output.output;
756
- else if (typeof output?.result === "string")
757
- output.result = _footerText + output.result;
758
- else if (typeof output?.text === "string")
759
- output.text = _footerText + output.text;
760
- else if (typeof output?.content === "string")
761
- output.content = _footerText + output.content;
755
+ if (footerTarget !== output && footerTarget && typeof footerTarget === "object") {
756
+ footerTarget.title = _footerText.trim();
757
+ }
758
+ if (typeof footerTarget?.output === "string")
759
+ footerTarget.output = _footerText + footerTarget.output;
760
+ else if (typeof footerTarget?.result === "string")
761
+ footerTarget.result = _footerText + footerTarget.result;
762
+ else if (typeof footerTarget?.text === "string")
763
+ footerTarget.text = _footerText + footerTarget.text;
764
+ else if (typeof footerTarget?.content === "string")
765
+ footerTarget.content = _footerText + footerTarget.content;
762
766
  else
763
- output.output = _footerText;
767
+ footerTarget.output = _footerText;
764
768
  _autoReportCount = (_autoReportCount || 0) + 1;
765
769
  if (_autoReportCount % 5 === 0 && ltTotal > 0) {
766
770
  saveReport({
@@ -847,30 +851,36 @@ export const onToolExecuteAfter = async (input, output) => {
847
851
  return s;
848
852
  });
849
853
  }
854
+ function _payload(obj) {
855
+ if (obj?.message && typeof obj.message === "object")
856
+ return obj.message;
857
+ return obj;
858
+ }
850
859
  // Inject pending delegation UI note (set in tool.execute.before).
851
860
  // This surfaces the warning in the OC chat transcript, not just stderr.
852
861
  if (pendingUiNote) {
862
+ const target = _payload(output);
853
863
  if (enforcementBlocked) {
854
864
  const note = `[vibeOS] ${pendingUiNote}`;
855
- if (typeof output?.result === "string")
856
- output.result += `\n\n${note}`;
857
- else if (typeof output?.text === "string")
858
- output.text += `\n\n${note}`;
859
- else if (typeof output?.content === "string")
860
- output.content += `\n\n${note}`;
865
+ if (typeof target?.result === "string")
866
+ target.result += `\n\n${note}`;
867
+ else if (typeof target?.text === "string")
868
+ target.text += `\n\n${note}`;
869
+ else if (typeof target?.content === "string")
870
+ target.content += `\n\n${note}`;
861
871
  else
862
- output.result = pendingUiNote;
872
+ target.result = pendingUiNote;
863
873
  }
864
874
  else {
865
875
  const note = `\n\n${pendingUiNote}`;
866
- if (typeof output?.result === "string")
867
- output.result += note;
868
- else if (typeof output?.text === "string")
869
- output.text += note;
870
- else if (typeof output?.content === "string")
871
- output.content += note;
876
+ if (typeof target?.result === "string")
877
+ target.result += note;
878
+ else if (typeof target?.text === "string")
879
+ target.text += note;
880
+ else if (typeof target?.content === "string")
881
+ target.content += note;
872
882
  else
873
- output.result = pendingUiNote;
883
+ target.result = pendingUiNote;
874
884
  }
875
885
  pendingUiNote = null;
876
886
  }