@akshar5/cohall 0.5.0 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1](https://github.com/AksharP5/cohall/compare/v0.5.0...v0.5.1) (2026-08-10)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **relay:** reject upgrades for legacy daemons ([#52](https://github.com/AksharP5/cohall/issues/52)) ([d4ab660](https://github.com/AksharP5/cohall/commit/d4ab660cce5489f6f572e221e71fc4ff6a412287))
9
+
3
10
  ## [0.5.0](https://github.com/AksharP5/cohall/compare/v0.4.10...v0.5.0) (2026-08-10)
4
11
 
5
12
 
package/README.md CHANGED
@@ -219,6 +219,8 @@ cohall upgrades abandon <operation-id>
219
219
 
220
220
  Upgrade requests are durable for offline devices and run after active delegated
221
221
  work. This is a typed owner-only maintenance operation, not remote shell access.
222
+ Every device must already run Cohall 0.5.0 or newer; upgrade older installations
223
+ individually once before using all-device upgrades.
222
224
  Each target must use a global npm, Bun, or pnpm installation that can upgrade
223
225
  itself. Preview the targets with `cohall upgrade --all --dry-run`, or pin an
224
226
  exact release with `--to 1.2.3`. `cohall upgrades` returns the 50 newest results.
package/bin/cohall.js CHANGED
@@ -17,9 +17,40 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
 
18
18
  // packages/protocol/src/index.ts
19
19
  import { Schema } from "effect";
20
- var version = "0.5.0", maxSocketPayloadBytes, bounded = (maxLength) => Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maxLength)), optionalText = (maxLength) => Schema.String.check(Schema.isMaxLength(maxLength)), boundedArray = (schema, maxLength) => Schema.Array(schema).check(Schema.isMaxLength(maxLength)), count, uuid = (name) => Schema.String.check(Schema.isUUID(4)).pipe(Schema.brand(name)), isoTimestamp = (name) => Schema.String.check(Schema.isPattern(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/, {
20
+ var version = "0.5.1", maxSocketPayloadBytes, bounded = (maxLength) => Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maxLength)), optionalText = (maxLength) => Schema.String.check(Schema.isMaxLength(maxLength)), boundedArray = (schema, maxLength) => Schema.Array(schema).check(Schema.isMaxLength(maxLength)), count, uuid = (name) => Schema.String.check(Schema.isUUID(4)).pipe(Schema.brand(name)), isoTimestamp = (name) => Schema.String.check(Schema.isPattern(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/, {
21
21
  expected: "an ISO-8601 UTC timestamp"
22
- })).pipe(Schema.brand(name)), DeviceId, ThreadId, MessageId, TaskId, AuthSessionId, OperationId, Timestamp, Platform, Provider, DeviceStatus, TaskStatus, OperationStatus, TaskTraceEventKind, MessageRole, ConnectionRole, AuthSession, CreatePairingInput, PairingCredential, ExchangePairingInput, SessionCredential, PairingResult, Capability, Workspace, Device, Thread, Message, Task, upgradeVersion, CreateUpgradeOperationsInput, DeviceOperation, TaskStatusCounts, ProviderUsage, DeviceUsage, UsageSummary, TaskTraceEvent, TaskTrace, ThreadContext, CreateTaskInput, SocketEvent, ErrorResponse, terminalTaskStatuses, isTerminalTask = (task) => terminalTaskStatuses.has(task.status), now = () => Timestamp.make(new Date().toISOString()), makeDeviceId = () => DeviceId.make(crypto.randomUUID()), makeThreadId = () => ThreadId.make(crypto.randomUUID()), makeMessageId = () => MessageId.make(crypto.randomUUID()), makeTaskId = () => TaskId.make(crypto.randomUUID()), makeAuthSessionId = () => AuthSessionId.make(crypto.randomUUID()), makeOperationId = () => OperationId.make(crypto.randomUUID()), decodeCreatePairingInput, decodeExchangePairingInput, decodeCreateTaskInput, decodeCreateUpgradeOperationsInput, decodeDevice, decodeSocketEvent;
22
+ })).pipe(Schema.brand(name)), DeviceId, ThreadId, MessageId, TaskId, AuthSessionId, OperationId, Timestamp, Platform, Provider, DeviceStatus, TaskStatus, OperationStatus, TaskTraceEventKind, MessageRole, ConnectionRole, AuthSession, CreatePairingInput, PairingCredential, ExchangePairingInput, SessionCredential, PairingResult, Capability, Workspace, Device, minimumDeviceOperationVersion = "0.5.0", parsedVersion = (value) => {
23
+ const match = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
24
+ if (match === null) {
25
+ return;
26
+ }
27
+ const core = match.slice(1, 4).map(Number);
28
+ if (core.length !== 3 || core.some((part) => !Number.isSafeInteger(part))) {
29
+ return;
30
+ }
31
+ return [core[0] ?? 0, core[1] ?? 0, core[2] ?? 0, match[4] !== undefined];
32
+ }, supportsDeviceOperations = (candidate) => {
33
+ if (candidate === "0.0.0-development") {
34
+ return true;
35
+ }
36
+ const current = parsedVersion(candidate);
37
+ const minimum = parsedVersion(minimumDeviceOperationVersion);
38
+ if (current === undefined || minimum === undefined) {
39
+ return false;
40
+ }
41
+ for (let index = 0;index < 3; index += 1) {
42
+ if (current[index] !== minimum[index]) {
43
+ return (current[index] ?? 0) > (minimum[index] ?? 0);
44
+ }
45
+ }
46
+ return !current[3];
47
+ }, assertDeviceOperationSupport = (devices) => {
48
+ const unsupported = devices.filter((device) => !supportsDeviceOperations(device.version));
49
+ if (unsupported.length === 0) {
50
+ return;
51
+ }
52
+ throw new Error(`All-device upgrades require Cohall ${minimumDeviceOperationVersion} or newer on every device. Upgrade individually first: ${unsupported.map((device) => `${device.name} (${device.version})`).join(", ")}`);
53
+ }, Thread, Message, Task, upgradeVersion, CreateUpgradeOperationsInput, DeviceOperation, TaskStatusCounts, ProviderUsage, DeviceUsage, UsageSummary, TaskTraceEvent, TaskTrace, ThreadContext, CreateTaskInput, SocketEvent, ErrorResponse, terminalTaskStatuses, isTerminalTask = (task) => terminalTaskStatuses.has(task.status), now = () => Timestamp.make(new Date().toISOString()), makeDeviceId = () => DeviceId.make(crypto.randomUUID()), makeThreadId = () => ThreadId.make(crypto.randomUUID()), makeMessageId = () => MessageId.make(crypto.randomUUID()), makeTaskId = () => TaskId.make(crypto.randomUUID()), makeAuthSessionId = () => AuthSessionId.make(crypto.randomUUID()), makeOperationId = () => OperationId.make(crypto.randomUUID()), decodeCreatePairingInput, decodeExchangePairingInput, decodeCreateTaskInput, decodeCreateUpgradeOperationsInput, decodeDevice, decodeSocketEvent;
23
54
  var init_src = __esm(() => {
24
55
  maxSocketPayloadBytes = 1024 * 1024;
25
56
  count = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }));
@@ -820,6 +851,7 @@ var PersistenceError, Service2, operationError = (operation) => (cause) => new P
820
851
  if (devices.length > 256) {
821
852
  throw new Error("All-device operations support at most 256 registered devices");
822
853
  }
854
+ assertDeviceOperationSupport(devices);
823
855
  for (const device of devices) {
824
856
  const outstanding = db.query(`SELECT COUNT(*) AS count FROM device_operations
825
857
  WHERE target_device_id = ? AND status IN ('queued', 'assigned', 'running')`).get(device.id);
@@ -4658,6 +4690,7 @@ var runCli = async (command, raw) => {
4658
4690
  const restart = !arguments_.options.has("no-restart");
4659
4691
  if (arguments_.options.has("dry-run")) {
4660
4692
  const devices = await Effect7.runPromise(relay2.devices());
4693
+ assertDeviceOperationSupport(devices);
4661
4694
  print({
4662
4695
  dry_run: true,
4663
4696
  requested_version: normalizedTarget,
@@ -5557,4 +5590,4 @@ await main().catch((cause) => {
5557
5590
  process.exitCode = 1;
5558
5591
  });
5559
5592
 
5560
- //# debugId=42161A8EF448D66964756E2164756E21
5593
+ //# debugId=2205AFF1105B05BB64756E2164756E21