@everfir/az8-cli 0.2.0-preview.4 → 0.2.0-preview.5

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
@@ -3,6 +3,18 @@
3
3
  All notable AZ8 CLI changes are recorded here. The CLI package has its own linear version sequence;
4
4
  it does not inherit the Web application or monorepo root version.
5
5
 
6
+ ## 0.2.0-preview.5 - 2026-07-22
7
+
8
+ ### Changed
9
+
10
+ - Canvas awareness names now preserve the authenticated user's Web-equivalent display name first
11
+ and append a CLI-owned parenthesized client suffix, defaulting to `(cli)`.
12
+ - `--client-name <suffix>` may override the client suffix for persistent and one-shot lifecycles,
13
+ but caller-provided parentheses are rejected so presence cannot obscure the name boundary.
14
+ - CLI attention awareness now publishes only the semantic cursor and omits selection bounds.
15
+ - `startGeneration` now carries valid Workflow execution-time estimates into the View Node's
16
+ generation history as Web-compatible median and maximum completion timestamps.
17
+
6
18
  ## 0.2.0-preview.4 - 2026-07-22
7
19
 
8
20
  ### Changed
package/README.md CHANGED
@@ -17,7 +17,7 @@ az8 guide
17
17
  For a supplied release artifact, install the exact immutable tarball instead:
18
18
 
19
19
  ```bash
20
- npm install --global ./everfir-az8-cli-0.2.0-preview.4.tgz
20
+ npm install --global ./everfir-az8-cli-0.2.0-preview.5.tgz
21
21
  az8 --version
22
22
  ```
23
23
 
@@ -124,7 +124,10 @@ az8 canvas operation <project-id> startGeneration \
124
124
  Operation input is one JSON object supplied by exactly one of `--input-stdin`, `--input-file`, or
125
125
  `--input-json`; omitted input defaults to `{}`. Input is limited to one MiB. `--timeout-ms` controls
126
126
  the same Operation acknowledgement or domain observation window as persistent stdio, and
127
- `--client-name` changes only the ephemeral awareness display name.
127
+ `--client-name` changes only the parenthesized client suffix of the ephemeral awareness name. The
128
+ authenticated display name always remains first: the default is `<current user> (cli)`, while
129
+ `--client-name codex` produces `<current user> (codex)`. Parentheses are owned by the CLI and are
130
+ rejected in caller-provided suffixes.
128
131
 
129
132
  Success writes one `az8.canvas.one-shot.v1` JSON document to stdout and exits `0`. A definitive
130
133
  input, validation, permission, or business failure writes structured JSON to stderr and exits `1`.
@@ -216,7 +219,7 @@ Canvas query, keep capability discovery and all ordered Operations in the same l
216
219
  it down only after the authoring task is complete.
217
220
 
218
221
  ```bash
219
- az8 canvas open <project-id> --write --format ndjson
222
+ az8 canvas open <project-id> --write --format ndjson [--client-name codex]
220
223
  ```
221
224
 
222
225
  The process writes one `hello` frame, then waits for an `initialize` request on stdin:
@@ -226,9 +229,12 @@ The process writes one `hello` frame, then waits for an `initialize` request on
226
229
  ```
227
230
 
228
231
  Before readiness the client hydrates the current authenticated account profile. Canvas Operations use
229
- that immutable account id and display name for persisted creator data. The `client.name` supplied by
230
- `initialize` is awareness-only and cannot impersonate or rename the persisted author. Project owner
231
- metadata is likewise never treated as the current actor on shared Projects.
232
+ that immutable account id and display name for persisted creator data. Awareness always displays the
233
+ authenticated name first and a CLI-owned parenthesized client suffix second. The default suffix is
234
+ `cli`; startup `--client-name` overrides it, otherwise `initialize.client.name` may provide it.
235
+ Caller suffixes cannot contain parentheses. This name is awareness-only and cannot impersonate or
236
+ rename the persisted author. The CLI publishes its Attention Cursor but deliberately omits selection
237
+ bounds. Project owner metadata is likewise never treated as the current actor on shared Projects.
232
238
 
233
239
  After `ready`, requests use `query`, `configureObservations`, `operation`, `reconnect`, or `shutdown`.
234
240
  The public authoring surface includes the note lifecycle, non-World View Node hierarchy operations,
@@ -311,6 +317,9 @@ explicitly submitting the same input. An uncertain backend or collaboration outc
311
317
  are acknowledged. It first estimates the exact current Draft inputs, then materializes literal Core
312
318
  Nodes and starts with the estimate's cost and Definition version. This estimate is internal: there is
313
319
  no public estimate Operation, balance query, caller-supplied expected cost, or second confirmation.
320
+ When the estimate includes execution-time ranges, the generation history records Web-compatible
321
+ median and maximum completion timestamps from the pre-submit time so Web can render the same expected
322
+ generation duration for a CLI-started Run.
314
323
  Waiting for a terminal result is deliberately a separate operation. Generation is a non-undoable
315
324
  Canvas History barrier. The CLI does not expose Assets, arbitrary Core Node creation, or 3D World
316
325
  operations.
package/RELEASE.md CHANGED
@@ -35,7 +35,7 @@ repository-wide `pnpm verify`. Publishing is an external action and requires exp
35
35
  authorization:
36
36
 
37
37
  ```bash
38
- npm publish ./tmp/az8-cli-release/everfir-az8-cli-0.2.0-preview.4.tgz --tag preview
38
+ npm publish ./tmp/az8-cli-release/everfir-az8-cli-0.2.0-preview.5.tgz --tag preview
39
39
  npm view @everfir/az8-cli dist-tags versions --json
40
40
  ```
41
41
 
package/dist/main.js CHANGED
@@ -4527,6 +4527,27 @@ var require_src2 = __commonJS({
4527
4527
  }
4528
4528
  });
4529
4529
 
4530
+ // src/canvas-awareness.ts
4531
+ var DEFAULT_CANVAS_CLIENT_NAME = "cli";
4532
+ function normalizeCanvasClientName(value) {
4533
+ const name = (value ?? DEFAULT_CANVAS_CLIENT_NAME).trim();
4534
+ if (!name) {
4535
+ throw invalidClientName("Canvas client name must not be empty.");
4536
+ }
4537
+ if (/[()]/.test(name)) {
4538
+ throw invalidClientName(
4539
+ "Canvas client name must not contain parentheses; AZ8 adds the required (name) suffix."
4540
+ );
4541
+ }
4542
+ return name;
4543
+ }
4544
+ function formatCanvasAwarenessName(actorDisplayName, clientName) {
4545
+ return `${actorDisplayName} (${normalizeCanvasClientName(clientName)})`;
4546
+ }
4547
+ function invalidClientName(message) {
4548
+ return Object.assign(new Error(message), { code: "invalid-client-name" });
4549
+ }
4550
+
4530
4551
  // ../../node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/math.js
4531
4552
  var floor = Math.floor;
4532
4553
  var abs = Math.abs;
@@ -22727,9 +22748,26 @@ function mapWorkflowRunEstimate(value, definitionId) {
22727
22748
  canAfford: value.can_afford,
22728
22749
  definitionId: value.definition_id,
22729
22750
  definitionVersion: value.definition_version,
22730
- estimatedCost: value.estimated_cost
22751
+ estimatedCost: value.estimated_cost,
22752
+ executionTimeRanges: (value.execution_time_ranges ?? []).flatMap((item) => {
22753
+ const range = item.range;
22754
+ if (!range || !isNonNegativeFinite(range.minSeconds) || !isNonNegativeFinite(range.maxSeconds) || !isNonNegativeFinite(range.medianSeconds) || !isNonNegativeFinite(range.sampleCount)) {
22755
+ return [];
22756
+ }
22757
+ return [
22758
+ {
22759
+ maxSeconds: range.maxSeconds,
22760
+ medianSeconds: range.medianSeconds,
22761
+ minSeconds: range.minSeconds,
22762
+ sampleCount: range.sampleCount
22763
+ }
22764
+ ];
22765
+ })
22731
22766
  };
22732
22767
  }
22768
+ function isNonNegativeFinite(value) {
22769
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
22770
+ }
22733
22771
  function mapWorkflowDefinition(value) {
22734
22772
  if (!value.id || !value.name || typeof value.version !== "number") {
22735
22773
  throw new Error("Workflow Runtime returned an invalid Definition.");
@@ -22903,7 +22941,8 @@ var CanvasSession = class {
22903
22941
  projectionRevision = 0;
22904
22942
  actorId = null;
22905
22943
  health;
22906
- async connect(displayName, onState) {
22944
+ async connect(clientName, onState) {
22945
+ const normalizedClientName = normalizeCanvasClientName(clientName);
22907
22946
  this.closeContext();
22908
22947
  this.transition("authenticating", onState);
22909
22948
  this.health.connectionAttempts += 1;
@@ -22927,7 +22966,10 @@ var CanvasSession = class {
22927
22966
  });
22928
22967
  this.document = document2;
22929
22968
  try {
22930
- document2.setIdentity({ accountId: actor.accountId, displayName });
22969
+ document2.setIdentity({
22970
+ accountId: actor.accountId,
22971
+ displayName: formatCanvasAwarenessName(actor.displayName, normalizedClientName)
22972
+ });
22931
22973
  this.transition("hydrating", onState);
22932
22974
  const foundationData = this.dependencies.foundationData ?? createAz8FoundationDataSystem(this.config);
22933
22975
  const projectContent = this.dependencies.projectContent ?? createAz8ProjectContentSystem(this.config);
@@ -23037,8 +23079,7 @@ var CanvasSession = class {
23037
23079
  }
23038
23080
  publishAttentionBounds(bounds) {
23039
23081
  this.requireDocument().setAttention({
23040
- cursor: { x: bounds.x + bounds.width + 24, y: bounds.y + bounds.height / 2 },
23041
- selection: bounds
23082
+ cursor: { x: bounds.x + bounds.width + 24, y: bounds.y + bounds.height / 2 }
23042
23083
  });
23043
23084
  }
23044
23085
  closeContext() {
@@ -23379,18 +23420,20 @@ function requirePositiveInteger(value, field) {
23379
23420
 
23380
23421
  // src/canvas-protocol-server.ts
23381
23422
  var CanvasProtocolServer = class {
23382
- constructor(config, projectId, output, session) {
23423
+ constructor(config, projectId, output, session, options = {}) {
23383
23424
  this.projectId = projectId;
23384
23425
  this.output = output;
23426
+ this.options = options;
23385
23427
  this.client = new CanvasClient(config, projectId, session);
23386
23428
  }
23387
23429
  projectId;
23388
23430
  output;
23431
+ options;
23389
23432
  client;
23390
23433
  initialized = false;
23391
23434
  shuttingDown = false;
23392
23435
  shutdownFinalized = false;
23393
- displayName = "AZ8 CLI";
23436
+ clientName = "cli";
23394
23437
  observationPreset = "compact";
23395
23438
  observationInclude = /* @__PURE__ */ new Set();
23396
23439
  recordedRequests = /* @__PURE__ */ new Map();
@@ -23533,8 +23576,11 @@ var CanvasProtocolServer = class {
23533
23576
  "initialize projectId does not match canvas open."
23534
23577
  );
23535
23578
  }
23579
+ const clientName = normalizeCanvasClientName(
23580
+ this.options.clientName ?? request.payload.client?.name
23581
+ );
23536
23582
  this.initialized = true;
23537
- this.displayName = request.payload.client?.name ?? "AZ8 CLI";
23583
+ this.clientName = clientName;
23538
23584
  this.observationPreset = request.payload.observationPreset ?? "compact";
23539
23585
  this.unsubscribeObservation = this.session.subscribe((observation) => {
23540
23586
  const category = observation.kind === "workflow" ? "workflow" : "canvas";
@@ -23558,7 +23604,7 @@ var CanvasProtocolServer = class {
23558
23604
  }
23559
23605
  async connect(requestId) {
23560
23606
  try {
23561
- await this.client.connect(this.displayName, (state) => {
23607
+ await this.client.connect(this.clientName, (state) => {
23562
23608
  void this.output.emitMandatory({ payload: { state }, requestId, type: "lifecycle" });
23563
23609
  });
23564
23610
  } catch (error) {
@@ -23936,7 +23982,7 @@ async function runCanvasOneShot(config, command, dependencies = {}) {
23936
23982
  try {
23937
23983
  assertProcessIndependent(command);
23938
23984
  client = dependencies.clientFactory?.(config, command.projectId) ?? new CanvasClient(config, command.projectId);
23939
- await client.connect(command.clientName ?? "AZ8 CLI one-shot");
23985
+ await client.connect(normalizeCanvasClientName(command.clientName));
23940
23986
  if (command.kind === "query") {
23941
23987
  return {
23942
23988
  exitCode: 0,
@@ -24159,7 +24205,7 @@ async function runCanvasMediaDownload(config, command, dependencies = {}) {
24159
24205
  try {
24160
24206
  client = dependencies.mediaDownloadClientFactory?.(config, command.projectId) ?? new CanvasClient(config, command.projectId);
24161
24207
  try {
24162
- await client.connect(command.clientName ?? "AZ8 CLI media download");
24208
+ await client.connect(normalizeCanvasClientName(command.clientName));
24163
24209
  } catch {
24164
24210
  throw new MediaDownloadError(
24165
24211
  "canvas-connection-failed",
@@ -25029,7 +25075,7 @@ function projectHelpOutput() {
25029
25075
  function canvasHelpOutput() {
25030
25076
  return [
25031
25077
  "Canvas:",
25032
- " az8 canvas open <project-id> --write --format ndjson",
25078
+ " az8 canvas open <project-id> --write --format ndjson [--client-name <suffix>]",
25033
25079
  " az8 canvas inspect <project-id> Print the latest persisted snapshot as JSON",
25034
25080
  " az8 canvas upload <project-id> --file <path> --idempotency-key <key>",
25035
25081
  " az8 canvas download <project-id> (--view-node-id <id> | --core-node-id <id>) --output <path>",
@@ -25042,7 +25088,7 @@ function canvasHelpOutput() {
25042
25088
  " --input-json <json> Read one inline JSON object",
25043
25089
  " --request-id <id> Set the Operation Receipt request ID",
25044
25090
  " --timeout-ms <ms> Set the operation acknowledgement timeout",
25045
- " --client-name <name> Set the ephemeral awareness display name",
25091
+ " --client-name <suffix> Set the parenthesized awareness client suffix",
25046
25092
  "",
25047
25093
  "One-shot query options:",
25048
25094
  " --view-node-id <id> Select one View Node for canvas.detail",
@@ -25235,7 +25281,15 @@ async function runPersistentCanvas(args2) {
25235
25281
  });
25236
25282
  try {
25237
25283
  const config = await resolveCliConfig(args2, {});
25238
- server = new CanvasProtocolServer(config, projectId, output);
25284
+ const requestedClientName = readOption3(args2, "--client-name");
25285
+ const clientName = requestedClientName ? normalizeCanvasClientName(requestedClientName) : void 0;
25286
+ server = new CanvasProtocolServer(
25287
+ config,
25288
+ projectId,
25289
+ output,
25290
+ void 0,
25291
+ clientName ? { clientName } : {}
25292
+ );
25239
25293
  const shutdownOnSignal = (signal) => {
25240
25294
  void server?.shutdownFromControl(signal.toLowerCase()).finally(() => process.stdin.destroy());
25241
25295
  };
@@ -25252,7 +25306,10 @@ async function runPersistentCanvas(args2) {
25252
25306
  }
25253
25307
  function readOption3(args2, name) {
25254
25308
  const index = args2.indexOf(name);
25255
- return index >= 0 ? args2[index + 1] : void 0;
25309
+ if (index < 0) return void 0;
25310
+ const value = args2[index + 1];
25311
+ if (!value || value.startsWith("--")) throw new Error(`${name} requires a value.`);
25312
+ return value;
25256
25313
  }
25257
25314
  function safeDiagnostic(error) {
25258
25315
  const message = error instanceof Error ? error.message : "Persistent Canvas client failed.";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everfir/az8-cli",
3
- "version": "0.2.0-preview.4",
3
+ "version": "0.2.0-preview.5",
4
4
  "description": "Semantic Project Canvas client for AZ8 Studio agents.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -46,8 +46,10 @@ capabilities instead of guessing operation names or input shapes.
46
46
  outcome, revisions, and optional usage. It is not Canvas History.
47
47
  - **History** contains reversible local interactions. Only Operations advertised as `undoable`
48
48
  participate. A generation start is a History barrier and is not undone by `undo`.
49
- - **Awareness** is ephemeral presence, client name, and Attention Cursor information. It never
50
- grants authority, changes persisted authorship, or proves a business result.
49
+ - **Awareness** is ephemeral presence, client suffix, and Attention Cursor information. The visible
50
+ name is always `<authenticated display name> (<client suffix>)`; the default suffix is `cli`.
51
+ CLI awareness does not publish selection bounds. Awareness never grants authority, changes
52
+ persisted authorship, or proves a business result.
51
53
  - **Actor** is the authenticated account from `AZ8_TOKEN`. A client or awareness name cannot
52
54
  impersonate another author.
53
55
 
@@ -131,6 +133,10 @@ and Operations, observe concurrent changes, and shut it down only after the Canv
131
133
  az8 canvas open <project-id> --write --format ndjson
132
134
  ```
133
135
 
136
+ Use `--client-name <suffix>` only when a more specific CLI presence label helps collaborators. The
137
+ CLI owns the surrounding parentheses, rejects parentheses in the supplied suffix, and always keeps
138
+ the authenticated user display name first.
139
+
134
140
  1. Continuously drain stdout; it is an ordered NDJSON protocol stream and may apply backpressure.
135
141
  2. Read `hello`, select protocol `1.0`, then send `initialize` for the same Project ID.
136
142
  3. Wait for `ready` before any query or Operation.
@@ -207,7 +213,9 @@ configuration option, modality, cost, or media compatibility from its display na
207
213
 
208
214
  The start Receipt may report `usage.credits.status` as `estimated`, `not-consumed`, or `unknown`.
209
215
  Estimated cost is informational, not final charged usage. There is no second confirmation. Never
210
- claim actual credit consumption from an estimate.
216
+ claim actual credit consumption from an estimate. When timing data is available, `startGeneration`
217
+ also records the same median and maximum completion timestamps Web uses to display expected duration;
218
+ these timestamps remain estimates and do not change the Run's completion boundary.
211
219
 
212
220
  ## Media
213
221
 
@@ -285,8 +293,8 @@ Never:
285
293
  or protocol payloads;
286
294
  - inspect, print, or edit an operator-provisioned credential source merely to check whether it
287
295
  exists; authenticate with a bounded read instead;
288
- - use awareness client names to impersonate persisted authors or treat Attention Cursor position as
289
- authority;
296
+ - use awareness client suffixes to impersonate persisted authors, supply parentheses to obscure the
297
+ authenticated-name boundary, or treat Attention Cursor position as authority;
290
298
  - use one-shot as if it retained History, Receipts, replay state, observations, or presence;
291
299
  - attempt Asset membership, arbitrary Core Node creation, 3D World editing, unsupported
292
300
  Decoration, alignment, or automatic layout through lower-level access;