@abelxiaoxing/cadence 2.0.18 → 2.0.20

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": "@abelxiaoxing/cadence",
3
- "version": "2.0.18",
3
+ "version": "2.0.20",
4
4
  "description": "Shared Pi task workspace: native terminal and WebUI, persistent service, checks and human review.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,6 +21,26 @@ function argumentsData(value, secrets) {
21
21
  if (sanitizer.limited) throw new Error("Unsupported context arguments");
22
22
  return parseWireJson(source, 64 * 1024);
23
23
  }
24
+ function own(value, key) {
25
+ const d =
26
+ value && typeof value === "object"
27
+ ? Object.getOwnPropertyDescriptor(value, key)
28
+ : undefined;
29
+ if (!d || !("value" in d)) throw new Error("Invalid usage");
30
+ return d.value;
31
+ }
32
+ // Pi adds optional usage breakdowns per provider and release (reasoning, cacheWrite1h);
33
+ // retain only the counts every assistant message carries, read as own data properties.
34
+ function counts(value, keys) {
35
+ const out = Object.create(null);
36
+ for (const key of keys) {
37
+ const n = own(value, key);
38
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 0)
39
+ throw new Error("Invalid usage");
40
+ out[key] = n;
41
+ }
42
+ return out;
43
+ }
24
44
  /** Deliberately retain text and tool exchanges, not just last assistant prose. */
25
45
  export function conversationMessages(messages, secrets = []) {
26
46
  return list(messages, 4096, (message) => {
@@ -54,27 +74,20 @@ export function conversationMessages(messages, secrets = []) {
54
74
  toolName: clean(message.toolName, secrets, 128),
55
75
  isError: message.isError === true,
56
76
  };
57
- const usage = closed(message.usage, [
77
+ const usage = counts(message.usage, [
58
78
  "input",
59
79
  "output",
60
80
  "cacheRead",
61
81
  "cacheWrite",
62
82
  "totalTokens",
63
- "cost",
64
83
  ]);
65
- const cost = closed(usage.cost, [
84
+ usage.cost = counts(own(message.usage, "cost"), [
66
85
  "input",
67
86
  "output",
68
87
  "cacheRead",
69
88
  "cacheWrite",
70
89
  "total",
71
90
  ]);
72
- for (const value of [
73
- ...Object.values(usage).filter((v) => typeof v !== "object"),
74
- ...Object.values(cost),
75
- ])
76
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
77
- throw new Error("Invalid usage");
78
91
  return {
79
92
  role,
80
93
  timestamp,
@@ -2,5 +2,5 @@
2
2
  export const nativeBuild = {
3
3
  kind: "native",
4
4
  contractHash:
5
- "944f3b53bd5b7f1d3f30868e0947d900e356ae9a2bcfb9f591edd988b3d5eb3a",
5
+ "83a2720c0a5a61f9e18e4f67e9738f184dee61cf07e75d9b98b5728577daaa6d",
6
6
  } as const;
@@ -66,6 +66,9 @@ export interface ChatTurn {
66
66
  status: ChatStatus;
67
67
  items: ChatItem[];
68
68
  notice: string;
69
+ /** Content kinds observed and not retained; never written into `notice`.
70
+ * `other` is a block of a type Cadence does not recognize. */
71
+ omitted: { thinking: boolean; media: boolean; other: boolean };
69
72
  }
70
73
  export interface ChatSummary {
71
74
  id: string;
@@ -199,12 +202,24 @@ export function decodeWorkbenchCommand(v: unknown): WorkbenchCommand {
199
202
  };
200
203
  }
201
204
  export function decodeChatTurn(v: unknown): ChatTurn {
202
- const o = closed(v, ["id", "epoch", "status", "items", "notice"]);
205
+ // Turns saved before `omitted` existed lack it; their flags read as unobserved.
206
+ const keys = ["id", "epoch", "status", "items", "notice"];
207
+ const current =
208
+ v !== null && typeof v === "object" && Object.hasOwn(v, "omitted");
209
+ const o = closed(v, current ? [...keys, "omitted"] : keys);
210
+ const omitted = current
211
+ ? closed(o.omitted, ["thinking", "media", "other"])
212
+ : null;
203
213
  return {
204
214
  id: decodeId(o.id),
205
215
  epoch: decodeId(o.epoch),
206
216
  status: oneOf(o.status, statuses),
207
217
  notice: text(o.notice, 1024),
218
+ omitted: {
219
+ thinking: omitted ? bool(omitted.thinking) : false,
220
+ media: omitted ? bool(omitted.media) : false,
221
+ other: omitted ? bool(omitted.other) : false,
222
+ },
208
223
  items: list(o.items, 256, (v) => {
209
224
  const i = closed(v, ["id", "role", "text", "name", "args", "error"]);
210
225
  return {
@@ -4006,12 +4006,20 @@ function decodeWorkbenchCommand(v) {
4006
4006
  };
4007
4007
  }
4008
4008
  function decodeChatTurn(v) {
4009
- const o = closed(v, ["id", "epoch", "status", "items", "notice"]);
4009
+ const keys2 = ["id", "epoch", "status", "items", "notice"];
4010
+ const current = v !== null && typeof v === "object" && Object.hasOwn(v, "omitted");
4011
+ const o = closed(v, current ? [...keys2, "omitted"] : keys2);
4012
+ const omitted = current ? closed(o.omitted, ["thinking", "media", "other"]) : null;
4010
4013
  return {
4011
4014
  id: decodeId(o.id),
4012
4015
  epoch: decodeId(o.epoch),
4013
4016
  status: oneOf(o.status, statuses),
4014
4017
  notice: text(o.notice, 1024),
4018
+ omitted: {
4019
+ thinking: omitted ? bool(omitted.thinking) : false,
4020
+ media: omitted ? bool(omitted.media) : false,
4021
+ other: omitted ? bool(omitted.other) : false
4022
+ },
4015
4023
  items: list(o.items, 256, (v2) => {
4016
4024
  const i = closed(v2, ["id", "role", "text", "name", "args", "error"]);
4017
4025
  return {
@@ -10285,7 +10293,7 @@ async function createGateway(value, hostUrl, source) {
10285
10293
  const input = decodeGatewayInput(value), store = new GatewayStore(input.serverConfig, input.stateHome);
10286
10294
  const web = loadWebAssets(source?.webDirectory);
10287
10295
  const build2 = {
10288
- contractHash: "944f3b53bd5b7f1d3f30868e0947d900e356ae9a2bcfb9f591edd988b3d5eb3a",
10296
+ contractHash: "83a2720c0a5a61f9e18e4f67e9738f184dee61cf07e75d9b98b5728577daaa6d",
10289
10297
  assets: {
10290
10298
  sourceHash: web.manifest.sourceHash,
10291
10299
  contractHash: web.manifest.contractHash,
@@ -21944,6 +21952,22 @@ function argumentsData(value, secrets) {
21944
21952
  throw new Error("Unsupported context arguments");
21945
21953
  return parseWireJson(source, 64 * 1024);
21946
21954
  }
21955
+ function own(value, key2) {
21956
+ const d = value && typeof value === "object" ? Object.getOwnPropertyDescriptor(value, key2) : undefined;
21957
+ if (!d || !("value" in d))
21958
+ throw new Error("Invalid usage");
21959
+ return d.value;
21960
+ }
21961
+ function counts(value, keys3) {
21962
+ const out = Object.create(null);
21963
+ for (const key2 of keys3) {
21964
+ const n = own(value, key2);
21965
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 0)
21966
+ throw new Error("Invalid usage");
21967
+ out[key2] = n;
21968
+ }
21969
+ return out;
21970
+ }
21947
21971
  function conversationMessages(messages, secrets = []) {
21948
21972
  return list(messages, 4096, (message) => {
21949
21973
  if (!message || typeof message !== "object")
@@ -21973,27 +21997,20 @@ function conversationMessages(messages, secrets = []) {
21973
21997
  toolName: clean(message.toolName, secrets, 128),
21974
21998
  isError: message.isError === true
21975
21999
  };
21976
- const usage = closed(message.usage, [
22000
+ const usage = counts(message.usage, [
21977
22001
  "input",
21978
22002
  "output",
21979
22003
  "cacheRead",
21980
22004
  "cacheWrite",
21981
- "totalTokens",
21982
- "cost"
22005
+ "totalTokens"
21983
22006
  ]);
21984
- const cost = closed(usage.cost, [
22007
+ usage.cost = counts(own(message.usage, "cost"), [
21985
22008
  "input",
21986
22009
  "output",
21987
22010
  "cacheRead",
21988
22011
  "cacheWrite",
21989
22012
  "total"
21990
22013
  ]);
21991
- for (const value of [
21992
- ...Object.values(usage).filter((v) => typeof v !== "object"),
21993
- ...Object.values(cost)
21994
- ])
21995
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
21996
- throw new Error("Invalid usage");
21997
22014
  return {
21998
22015
  role: role2,
21999
22016
  timestamp,
@@ -24852,7 +24869,7 @@ class TaskActions {
24852
24869
  const graph = action.kind === "start" ? plan?.graph ?? this.defaultGraph(selected2.record, selected2.identity, expected.model) : null;
24853
24870
  if (graph && hash2(canonicalJson(graph)) !== expected.task.graphIdentity)
24854
24871
  throw new ContractError("stale");
24855
- let own2 = {
24872
+ let own3 = {
24856
24873
  revision: selected2.record.revision,
24857
24874
  identity: selected2.identity
24858
24875
  };
@@ -24882,7 +24899,7 @@ class TaskActions {
24882
24899
  try {
24883
24900
  this.assertChoice(expected);
24884
24901
  const latest = h.coordination.store.loadSnapshot(action.taskId);
24885
- return latest?.identity === own2.identity && latest.record.revision === own2.revision && this.sources.current();
24902
+ return latest?.identity === own3.identity && latest.record.revision === own3.revision && this.sources.current();
24886
24903
  } catch {
24887
24904
  return false;
24888
24905
  }
@@ -24910,7 +24927,7 @@ class TaskActions {
24910
24927
  });
24911
24928
  if (publication.status !== "published" || !publication.observed)
24912
24929
  throw new ContractError("conflict");
24913
- own2 = publication.observed;
24930
+ own3 = publication.observed;
24914
24931
  }
24915
24932
  });
24916
24933
  accepted2.activate(work);
@@ -25149,6 +25166,11 @@ import { dirname as dirname14, join as join22 } from "node:path";
25149
25166
  var TURN_BYTES = 384 * 1024;
25150
25167
  var META_BYTES = 64 * 1024;
25151
25168
  var SESSION_LIMIT = 200;
25169
+ var OMITTED_FLAG = {
25170
+ "hidden-thinking": "thinking",
25171
+ binary: "media",
25172
+ unsupported: "other"
25173
+ };
25152
25174
 
25153
25175
  class ConversationCapture {
25154
25176
  turn;
@@ -25242,8 +25264,8 @@ class ConversationCapture {
25242
25264
  item.error = e.isError;
25243
25265
  } else if (e.kind === "worker-failure")
25244
25266
  this.turn.notice = `worker-failure: ${e.code}`;
25245
- else if (e.kind === "omitted-block")
25246
- this.turn.notice = "Hidden thinking, signatures and media are not retained.";
25267
+ else if (e.kind === "omitted-block" && e.block.owner.kind !== "context" && e.block.owner.kind !== "handoff")
25268
+ this.turn.omitted[OMITTED_FLAG[e.block.reason]] = true;
25247
25269
  if ([...this.details.values()].reduce((size, detail) => size + Buffer.byteLength(detail.text) + detail.sanitizer.retainedBytes, 0) > TURN_BYTES)
25248
25270
  throw new ContractError("capacity");
25249
25271
  canonicalJson(this.turn, TURN_BYTES);
@@ -25500,6 +25522,7 @@ class Conversations {
25500
25522
  epoch: input.model.epoch,
25501
25523
  status: "queued",
25502
25524
  notice: "",
25525
+ omitted: { thinking: false, media: false, other: false },
25503
25526
  items: [
25504
25527
  {
25505
25528
  id: "user",
@@ -25925,7 +25948,7 @@ function refuseAt(stage, step) {
25925
25948
  }
25926
25949
  }
25927
25950
  async function createServiceHost(value, sourceBuild) {
25928
- const embedded = "944f3b53bd5b7f1d3f30868e0947d900e356ae9a2bcfb9f591edd988b3d5eb3a";
25951
+ const embedded = "83a2720c0a5a61f9e18e4f67e9738f184dee61cf07e75d9b98b5728577daaa6d";
25929
25952
  if (embedded && sourceBuild)
25930
25953
  throw new ContractError("unsupported-context");
25931
25954
  const contractHash = decodeHash(embedded ?? sourceBuild?.contractHash);