@celilo/core 0.12.0 → 0.13.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celilo/core",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Lightweight shared core for Celilo CLI tools — command registry, NDJSON API protocol, and remote SSH client. No Ink/React/drizzle/aws-sdk transitive deps, so an MCP server can reach the transport without installing the full CLI.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -1751,6 +1751,45 @@ export const COMMANDS: CommandDef[] = [
1751
1751
  description:
1752
1752
  'Per-subscriber delivery history (success rate, last delivery, recent failures)',
1753
1753
  },
1754
+ {
1755
+ name: 'install-daemon',
1756
+ description: 'Write a supervisor unit (systemd/launchd) for the build-bus webhook receiver',
1757
+ flags: [
1758
+ {
1759
+ name: 'system',
1760
+ description: 'System-scope unit (/etc/systemd/system or LaunchDaemons)',
1761
+ takesValue: false,
1762
+ },
1763
+ {
1764
+ name: 'secret',
1765
+ description:
1766
+ 'Shared HMAC secret incoming webhooks sign with (or CELILO_BUS_SECRET env)',
1767
+ takesValue: true,
1768
+ },
1769
+ { name: 'port', description: 'TCP port to listen on (default 8123)', takesValue: true },
1770
+ {
1771
+ name: 'dispatch',
1772
+ description:
1773
+ 'Render a combined unit (receiver + hook dispatcher) for boxes with no events daemon',
1774
+ takesValue: false,
1775
+ },
1776
+ {
1777
+ name: 'print',
1778
+ description: 'Render the unit to stdout without writing (Ansible seam)',
1779
+ takesValue: false,
1780
+ },
1781
+ {
1782
+ name: 'celilo-path',
1783
+ description: 'Explicit celilo binary path for ExecStart',
1784
+ takesValue: true,
1785
+ },
1786
+ ],
1787
+ },
1788
+ {
1789
+ name: 'uninstall-daemon',
1790
+ description: 'Remove the build-bus receiver supervisor unit',
1791
+ flags: [{ name: 'system', description: 'System-scope unit', takesValue: false }],
1792
+ },
1754
1793
  ],
1755
1794
  },
1756
1795
  {
package/src/protocol.ts CHANGED
@@ -100,6 +100,14 @@ export type ProgressMessage = z.infer<typeof ProgressMessageSchema>;
100
100
  export const LogMessageSchema = z.object({
101
101
  type: z.literal('log'),
102
102
  message: z.string(),
103
+ /**
104
+ * Which child stream the line came from. The server merges nothing —
105
+ * each stream is pumped separately — but the message schema is the only
106
+ * place the distinction can survive the trip, so it is recorded here
107
+ * (celilo#1362). Optional so an older client parses a newer server
108
+ * unchanged; unmarked lines are stdout.
109
+ */
110
+ stream: z.enum(['stdout', 'stderr']).optional(),
103
111
  });
104
112
  export type LogMessage = z.infer<typeof LogMessageSchema>;
105
113
 
@@ -190,6 +190,11 @@ function applyMessage(
190
190
  // Nest under the active step so the footer isn't corrupted; otherwise print.
191
191
  if (display.hasPending) {
192
192
  display.subEvent(msg.message);
193
+ } else if (msg.stream === 'stderr') {
194
+ // The server names each log line's origin stream; keep stderr on
195
+ // stderr locally so diagnostics never masquerade as command output
196
+ // (celilo#1362). Unmarked lines are stdout from an older server.
197
+ process.stderr.write(`${msg.message}\n`);
193
198
  } else {
194
199
  out.write(`${msg.message}\n`);
195
200
  }