@dassi_ai/cli 0.7.0 → 0.7.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/README.md CHANGED
@@ -138,20 +138,20 @@ dassi launch --stop dev
138
138
 
139
139
  Launch supports `--dist`, `--chrome`, `--profile-dir`, `--load-mode auto|pipe|flag`, and Chrome arguments after `--`. Branded Chrome uses a detached helper holding a CDP pipe for the unpacked extension; Chromium/Chrome for Testing can use `--load-extension` directly.
140
140
 
141
- CLI 0.7 requires the current extension with live tool discovery, and CLI protocol 3 for task submission. Incompatible clients, daemons, and extensions fail before a task is submitted, in either upgrade order. After upgrading the CLI, finish any old CLI calls and restart an older daemon if prompted (its PID is in `~/.dassi/default.pid`). Browser conversations survive a daemon restart. This package is not auto-published by a source change.
141
+ CLI 0.7 requires the current extension with live tool discovery, and CLI protocol 3 for task submission. Incompatible clients, daemons, and extensions fail before a task is submitted, in either upgrade order. After upgrading the CLI, finish any old CLI calls and restart an older daemon if prompted (its PID is in `~/.dassi/default.pid`). Browser conversations survive a daemon restart. Merging a `cli/package.json` version bump to `main` publishes this package (`.github/workflows/publish-cli.yml`, npm trusted publishing); an extension release is blocked until the CLI on npm speaks the protocol it requires.
142
142
 
143
143
  `run --timeout` is rejected with migration instructions. Use `--wait` to observe and `stop` to cancel. Scripts must check task status and explicitly stop a task if they impose an execution budget. `--session`/`DASSI_SESSION` are retained for development compatibility; they select a daemon socket, not a browser or conversation. Normal use needs neither. `DASSI_BRIDGE_PORT` configures an isolated development bridge.
144
144
 
145
145
  The daemon routes short requests. Native runtime admission controls each conversation; the daemon does not serialize unrelated profiles or hold a connection for a task's lifetime. Startup requires no sign-in. The native conversation owns admission, cancellation, recovery, and transcript. Status reads its transcript and state in one storage transaction; a single last-run summary survives later compaction. There is no per-prompt task ledger.
146
146
 
147
- Before promoting a CLI release to npm `latest`, make its compatible extension available in the Chrome Web Store. Check the packed npm artifact in a fresh global prefix, then verify setup against that store installation: extension confirmation, signed-out browser access, profile choice, agent discovery, an initial tab listing, and resume after interruption. Local builds and injected browser responses do not establish that store-to-npm release path.
147
+ A protocol bump ships CLI first: the CLI publishes on merge, and the extension release refuses to tag until npm `latest` declares that protocol (`scripts/check-cli-on-npm.sh` reads `dassi.protocol` from `cli/package.json` via `npm view`). While the matching extension is still in Chrome Web Store review, a freshly installed CLI reports that the extension is older and must be updated; CLIs already installed keep working against the store build. Check the packed npm artifact in a fresh global prefix, then verify setup against that store installation: extension confirmation, signed-out browser access, profile choice, agent discovery, an initial tab listing, and resume after interruption. Local builds and injected browser responses do not establish that store-to-npm release path.
148
148
 
149
149
  ## Output for scripts
150
150
 
151
151
  Browser and task commands with `--json` write their response to stdout, including argument, setup, and connection failures:
152
152
 
153
153
  ```json
154
- {"success": false, "error": "An older Dassi daemon is running. Finish active tasks, restart the daemon, then retry with this CLI."}
154
+ {"success": false, "error": "An older Dassi daemon is running. Finish active tasks, stop it (kill the PID in ~/.dassi/default.pid), then retry with this CLI."}
155
155
  ```
156
156
 
157
157
  Parse stdout even on a nonzero exit. Successful responses contain `data`; failures contain `error`. Direct group tools return an array of `{tabId, response}`. Task status, rather than exit zero alone, tells you whether delegated work finished. `--help`, `--version`, and `skill` also support JSON, with a string in `data`. Development `launch` commands use terminal output.
package/daemon-client.mjs CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  getSocketPath,
10
10
  CLI_PROTOCOL_VERSION,
11
11
  getReadyFile,
12
+ getPidFile,
12
13
  isDaemonRunning,
13
14
  parseReadyPayload,
14
15
  CHROME_WEB_STORE_URL,
@@ -156,7 +157,8 @@ export async function ensureDaemonReady(session) {
156
157
  }
157
158
 
158
159
  if (ready.status === 'error') throw new Error(ready.error);
159
- if (ready.protocolVersion !== CLI_PROTOCOL_VERSION) throw new Error('An older Dassi daemon is running. Finish active tasks, restart the daemon, then retry with this CLI.');
160
+ if (ready.protocolVersion > CLI_PROTOCOL_VERSION) throw new Error(`A newer Dassi daemon is running (protocol ${ready.protocolVersion}, this CLI speaks ${CLI_PROTOCOL_VERSION}). Run \`npm install -g @dassi_ai/cli@latest\` and retry.`);
161
+ if (ready.protocolVersion !== CLI_PROTOCOL_VERSION) throw new Error(`An older Dassi daemon is running. Finish active tasks, stop it (kill the PID in ${getPidFile(session)}), then retry with this CLI.`);
160
162
 
161
163
  return socketPath;
162
164
  }
package/dassi-daemon.mjs CHANGED
@@ -182,11 +182,15 @@ export async function dispatchToExtension(cmd, reg = registry) {
182
182
  }
183
183
 
184
184
  /** Discovery is independent of authentication and in-flight agent work. */
185
+ const session = validateSession(process.env.DASSI_SESSION ?? 'default');
186
+
185
187
  export async function routeCommand(cmd, reg = registry, dispatch = dispatchToExtension) {
186
188
  let resolvedProfile;
187
189
  const call = (command) => dispatch(command, reg);
188
190
  try {
189
- if (['run', 'task_status', 'task_stop'].includes(cmd.action) && cmd.protocolVersion !== CLI_PROTOCOL_VERSION) throw new Error('Incompatible CLI. Update Dassi CLI and restart its daemon.');
191
+ if (['run', 'task_status', 'task_stop'].includes(cmd.action) && cmd.protocolVersion !== CLI_PROTOCOL_VERSION) throw new Error(cmd.protocolVersion > CLI_PROTOCOL_VERSION
192
+ ? `This Dassi daemon is older than the CLI (daemon protocol ${CLI_PROTOCOL_VERSION}, CLI ${cmd.protocolVersion}). Stop it (kill the PID in ${getPidFile(session)}) and retry.`
193
+ : `Incompatible CLI (protocol ${cmd.protocolVersion ?? 'none'}, this daemon speaks ${CLI_PROTOCOL_VERSION}). Run \`npm install -g @dassi_ai/cli@latest\` and retry.`);
190
194
  let target = cmd.target ?? null;
191
195
  let localTaskId = cmd.taskId;
192
196
  if (cmd.action === 'task_status' || cmd.action === 'task_stop' || (cmd.action === 'run' && cmd.taskId)) {
@@ -347,7 +351,6 @@ function startIdleShutdown(server, session, getLastCommandAt) {
347
351
  * @returns {Promise<void>}
348
352
  */
349
353
  export async function startDaemon() {
350
- const session = validateSession(process.env.DASSI_SESSION ?? 'default');
351
354
  const { socketPath, readyFile } = initDaemonProcess(session);
352
355
 
353
356
  try {
package/dassi-shared.mjs CHANGED
@@ -1,4 +1,3 @@
1
- export const CLI_PROTOCOL_VERSION = 3;
2
1
  /**
3
2
  * Dassi CLI Shared Utilities
4
3
  *
@@ -10,6 +9,12 @@ export const CLI_PROTOCOL_VERSION = 3;
10
9
  import * as fs from 'fs';
11
10
  import * as path from 'path';
12
11
  import * as os from 'os';
12
+ import { fileURLToPath } from 'url';
13
+
14
+ const PACKAGE = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'package.json'), 'utf8'));
15
+ export const CLI_VERSION = PACKAGE.version;
16
+ /** Lives in package.json so the extension release gate can read it from npm (`npm view … dassi.protocol`) without downloading the tarball. */
17
+ export const CLI_PROTOCOL_VERSION = PACKAGE.dassi.protocol;
13
18
 
14
19
  // ─── Extension identity ───────────────────────────────────────────────────────
15
20
 
package/dassi.mjs CHANGED
@@ -9,7 +9,7 @@ import * as path from 'path';
9
9
  import * as child_process from 'child_process';
10
10
  import { randomUUID } from 'node:crypto';
11
11
  import { fileURLToPath, pathToFileURL } from 'url';
12
- import { getSocketPath, validateSession, getAppDir, getLaunchesFile } from './dassi-shared.mjs';
12
+ import { getSocketPath, validateSession, getAppDir, getLaunchesFile, CLI_VERSION } from './dassi-shared.mjs';
13
13
  import { ensureDaemonRunning, sendCommand, sendAndWait, ensureDaemonReady } from './daemon-client.mjs';
14
14
  import { dispatchLaunch } from './launch.mjs';
15
15
  import { parseToolCommand, requireTarget, parseStrictInt, parseTarget, parseWait } from './tool-commands.mjs';
@@ -18,7 +18,6 @@ import { formatResponse } from './format-response.mjs';
18
18
  import { HELP_TEXT } from './help-text.mjs';
19
19
 
20
20
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
- const VERSION = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8')).version;
22
21
 
23
22
  // ─── Arg parsing ──────────────────────────────────────────────────────────────
24
23
 
@@ -243,7 +242,7 @@ function consumeFlag(args, flag) {
243
242
 
244
243
  function handleImmediateAction({ action, params, json }) {
245
244
  let text;
246
- if (action === 'version') text = VERSION;
245
+ if (action === 'version') text = CLI_VERSION;
247
246
  else if (action === 'help') text = HELP_TEXT;
248
247
  else if (action === 'skill') {
249
248
  const skillDir = path.join(__dirname, 'skills', 'dassi');
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@dassi_ai/cli",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "CLI for the Dassi Chrome extension \u2014 run browser automation from the terminal",
5
5
  "type": "module",
6
+ "dassi": {
7
+ "protocol": 3
8
+ },
6
9
  "bin": {
7
10
  "dassi": "./dassi.mjs"
8
11
  },