@chipschat/opencode 1.0.12 → 1.0.14

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.
@@ -1,9 +1,9 @@
1
1
  # Third-party notices
2
2
 
3
- `dist/main.js` in @chipschat/opencode 1.0.12 carries these packages, bundled in. Each one's
3
+ `dist/main.js` in @chipschat/opencode 1.0.14 carries these packages, bundled in. Each one's
4
4
  licence follows.
5
5
 
6
- ## @chipschat/harness 1.0.1 (Apache-2.0)
6
+ ## @chipschat/harness 1.0.2 (Apache-2.0)
7
7
 
8
8
  Apache License
9
9
  Version 2.0, January 2004
@@ -207,7 +207,7 @@ Apache License
207
207
  See the License for the specific language governing permissions and
208
208
  limitations under the License.
209
209
 
210
- ## @chipschat/protocol 1.0.1 (Apache-2.0)
210
+ ## @chipschat/protocol 1.0.2 (Apache-2.0)
211
211
 
212
212
  Apache License
213
213
  Version 2.0, January 2004
package/dist/main.js CHANGED
@@ -20527,7 +20527,7 @@ var contextLine = external_exports.object({
20527
20527
  }).describe("One line of a room: something said, or something that happened to who is in it.");
20528
20528
  var roomContext = external_exports.object({
20529
20529
  lines: external_exports.array(contextLine).max(CONTEXT_CEILING.lines).describe("Oldest first, the newest that fit the budget."),
20530
- since_seq: external_exports.int().nonnegative().describe("Where they start: after this `seq`. With a message, where the turn that said the harness's own last message in the room began (ADR 0105), else its joining; from the pull route, 0."),
20530
+ since_seq: external_exports.int().nonnegative().describe("Where they start: after this `seq`. With a message, where the harness's own last turn in the room began, one that said something or passed with NO_REPLY (ADR 0105), else its joining; from the pull route, 0."),
20531
20531
  truncated: external_exports.boolean().describe("Whether older lines after `since_seq` were left out to fit the budget."),
20532
20532
  before: external_exports.int().positive().describe("A cursor: `GET /v1/spaces/:id/context?before=` this reads what came before these lines."),
20533
20533
  files: roomFiles.max(ROOM_FILES_IN_CONTEXT).optional().describe("The room's files at their current version, newest first, the 20 newest (ADR 0099): with a message, as of it, its own files included; from the pull route, as of now. Each with a URL for this harness. Absent from a Chips before files, and when the room has none."),
@@ -21675,6 +21675,7 @@ var pairingPayload = external_exports.object({
21675
21675
  var JOIN_POLL_SECONDS = 3;
21676
21676
  var joinKind = external_exports.enum(["harness", "device", "invite", "pairing"]).describe("A harness asking for a key; a device asking to be paired; a person joining by an invite, or a device pairing by a code, that waits for whoever handed it out (ADR 0232).");
21677
21677
  var keyCode = external_exports.string().regex(/^[0-9]{6}$/, "six digits");
21678
+ var joinNonce = external_exports.string().regex(/^[A-Za-z0-9_-]{43}$/, "32 bytes, base64url");
21678
21679
  var requestCode = external_exports.union([pairingCode, keyCode]);
21679
21680
  var joinState = external_exports.enum(["waiting", "allowed", "denied", "expired", "redeemed"]).describe("`waiting` for a person; `allowed`, and not yet collected; `denied` by a person, or withdrawn; `expired` before it was collected; `redeemed`, which spends it.");
21680
21681
  var joinStartedBy = external_exports.enum(["requester", "person"]).describe("Who started it: the requester, with a code to compare, or a person, with a link that is allowed already.");
@@ -21710,12 +21711,15 @@ var joinAsk = external_exports.object({
21710
21711
  software: words2(120).optional(),
21711
21712
  machine: words2(120).optional(),
21712
21713
  wants: capabilities.optional().describe("For a harness: what it asks to be allowed."),
21713
- public_key: external_exports.string().regex(/^[A-Za-z0-9+/]{40,64}={0,2}$/).optional().describe("For a device: the public half of its Ed25519 key, SPKI DER, base64.")
21714
+ public_key: external_exports.string().regex(/^[A-Za-z0-9+/]{40,64}={0,2}$/).optional().describe("For a device: the public half of its Ed25519 key, SPKI DER, base64."),
21715
+ commit: joinNonce.optional().describe("For a device (S-1, ADR 0278): the SHA-256 of `joinCommitText` of a nonce it keeps, base64url. It sends the nonce with its first poll, once it holds the server's, and both ends work the code out.")
21714
21716
  }).describe("A request to join.");
21715
21717
  var joinAsked = external_exports.object({
21716
21718
  request_id: id("join"),
21717
21719
  secret: external_exports.string().min(16).max(200).describe("The requester's alone: it polls with it."),
21718
- code: requestCode,
21720
+ code: requestCode.optional().describe("The code to show. Absent for a device that sent `commit`: it works its own out."),
21721
+ server_key: external_exports.string().min(1).max(128).optional().describe("For a device that sent `commit`: the server's tunnel key, which the code is worked out from and the device pins once it is allowed (ADR 0191, 0278)."),
21722
+ nonce: joinNonce.optional().describe("For a device that sent `commit`: the server's nonce, for the code (ADR 0278)."),
21719
21723
  expires_in: external_exports.int().positive().describe("Seconds until it expires."),
21720
21724
  interval: external_exports.int().positive().describe("Seconds between polls.")
21721
21725
  });
@@ -22647,6 +22651,17 @@ var jobChangeFrame = external_exports.object({
22647
22651
  asked_at: isoTimestamp
22648
22652
  }).describe("A person switched one of a harness's own jobs, or changed how often it runs (ADR 0252). Sent to a harness's socket that said `jobs` in its `hello`, now or never: it is not in the log. The harness answers with its copy of all its jobs, `answers` or `refuses` naming `change_id`.");
22649
22653
 
22654
+ // node_modules/@chipschat/protocol/dist/src/read-marks.js
22655
+ var READ_MARKS_MAX = 1e3;
22656
+ var readMarks = external_exports.record(id("space"), external_exports.int().nonnegative().describe("The `seq` the room is read up to.")).refine((marks) => Object.keys(marks).length <= READ_MARKS_MAX, {
22657
+ message: `at most ${READ_MARKS_MAX} rooms`
22658
+ }).describe("How far each room is read, by room id.");
22659
+ var readMarksBody = external_exports.object({ spaces: readMarks });
22660
+ var readFrame = external_exports.object({
22661
+ frame: external_exports.literal("read"),
22662
+ spaces: readMarks.describe("The rooms whose marks moved, and where to.")
22663
+ }).describe("A person read further in some rooms, on one of their devices (ADR 0262). Sent to that person's sockets that said `reads` in their `hello`, never to anyone else's, now or never: `GET /v1/me/read` reads them again.");
22664
+
22650
22665
  // node_modules/@chipschat/protocol/dist/src/frames.js
22651
22666
  var clientHelloFrame = external_exports.object({
22652
22667
  frame: external_exports.literal("hello"),
@@ -22663,7 +22678,7 @@ var clientHelloFrame = external_exports.object({
22663
22678
  autonomy: autonomyLevel.optional().describe("The level the harness believes it has.")
22664
22679
  })).max(64).optional().describe("Not read by Chips: a connection is its token's, and the server's `hello` names the token's harness and its agents (ADR 0087). Absent for a person's client."),
22665
22680
  since: external_exports.int().nonnegative().optional().describe("Not read by Chips: a stream resumes from `subscribe`'s `since`."),
22666
- accepts: external_exports.array(external_exports.string().min(1).max(40)).max(32).optional().describe("Server frames beyond the base set this client understands, by the names in `SERVER_EXTENSIONS`. A name the server does not know is ignored rather than refused, so a client may name a frame a newer server sends and still be answered by an older one (ADR 0211, Phase 3). A client that says `events` is sent its replay in pages rather than one frame per event; one that says `presence` is sent an agent's state as it changes (ADR 0083); a harness's socket that says `restart` is sent `restart` when a person asks it to restart (ADR 0094); an owner's or admin's that says `join` is sent each join request as it changes (ADR 0122); a harness's that says `context` is sent `context.edit` when a person changes one of its context files (ADR 0134); a harness's that says `models` is sent `model.change` when a person changes an agent's model or effort (ADR 0140); a harness's that says `heartbeats` is sent `heartbeat.change` when a person switches an agent's heartbeat or changes how often it beats (ADR 0143); a harness's that says `context_windows` is sent `context_window.compact` and `context_window.change` when a person asks an agent to compact now or changes the limit it compacts itself at (ADR 0146); a harness's that says `jobs` is sent `job.change` when a person switches one of the jobs it runs on its own (ADR 0252); a person's that says `folders` is sent `folder.open` when they ask, from another of their devices, for a room's folder to be opened in Finder (ADR 0225), and `folder.run` when they ask for its project to be run or stopped there (ADR 0226); a person's that says `folder_runs` is sent `folder.run_state` when their Mac says how a run of theirs stands (ADR 0226); one that says nothing is sent what it was always sent, since an unknown frame is dropped in silence."),
22681
+ accepts: external_exports.array(external_exports.string().min(1).max(40)).max(32).optional().describe("Server frames beyond the base set this client understands, by the names in `SERVER_EXTENSIONS`. A name the server does not know is ignored rather than refused, so a client may name a frame a newer server sends and still be answered by an older one (ADR 0211, Phase 3). A client that says `events` is sent its replay in pages rather than one frame per event; one that says `presence` is sent an agent's state as it changes (ADR 0083); a harness's socket that says `restart` is sent `restart` when a person asks it to restart (ADR 0094); an owner's or admin's that says `join` is sent each join request as it changes (ADR 0122); a harness's that says `context` is sent `context.edit` when a person changes one of its context files (ADR 0134); a harness's that says `models` is sent `model.change` when a person changes an agent's model or effort (ADR 0140); a harness's that says `heartbeats` is sent `heartbeat.change` when a person switches an agent's heartbeat or changes how often it beats (ADR 0143); a harness's that says `context_windows` is sent `context_window.compact` and `context_window.change` when a person asks an agent to compact now or changes the limit it compacts itself at (ADR 0146); a harness's that says `jobs` is sent `job.change` when a person switches one of the jobs it runs on its own (ADR 0252); a person's that says `folders` is sent `folder.open` when they ask, from another of their devices, for a room's folder to be opened in Finder (ADR 0225), and `folder.run` when they ask for its project to be run or stopped there (ADR 0226); a person's that says `folder_runs` is sent `folder.run_state` when their Mac says how a run of theirs stands (ADR 0226); a person's that says `reads` is sent `read` when they read further on another of their devices (ADR 0262); one that says nothing is sent what it was always sent, since an unknown frame is dropped in silence."),
22667
22682
  context: contextBudget.optional().describe("How much of a room a harness is handed with each message for it (ADR 0088): 40 lines and 16,000 characters when absent, 200 and 32,000 at most. For this connection. A person's client is handed none.")
22668
22683
  }).describe("The first frame a client sends.");
22669
22684
  var subscribeFrame = external_exports.object({
@@ -22789,6 +22804,7 @@ var serverFrame = external_exports.discriminatedUnion("frame", [
22789
22804
  folderOpenFrame,
22790
22805
  folderRunFrame,
22791
22806
  folderRunStateFrame,
22807
+ readFrame,
22792
22808
  contextEditFrame,
22793
22809
  modelChangeFrame,
22794
22810
  heartbeatChangeFrame,
@@ -22840,9 +22856,37 @@ var HTML_POLICY = "default-src 'none'; img-src data: blob:; font-src data:; medi
22840
22856
  var PAGE_SANDBOX = "allow-scripts allow-popups allow-popups-to-escape-sandbox";
22841
22857
  var PAGE_HEADER_POLICY = `${HTML_POLICY}; sandbox ${PAGE_SANDBOX}`;
22842
22858
 
22843
- // node_modules/@chipschat/harness/dist/connect.js
22844
- import { readFile as readFile2 } from "node:fs/promises";
22845
- import { basename } from "node:path";
22859
+ // node_modules/@chipschat/protocol/dist/src/push.js
22860
+ var PUSH_WORDS = {
22861
+ /** An ask of an agent's that waits on a person (ADR 0045). */
22862
+ decision: {
22863
+ title: "A decision is waiting",
22864
+ body: "Approve or deny from here.",
22865
+ categoryId: "decision"
22866
+ },
22867
+ /** A message that @s the person, or was sent to them (ADR 0158). */
22868
+ messageForYou: { title: "A message for you", body: "Open Chips to read it." },
22869
+ /** A message in a room they hear (ADR 0158). */
22870
+ message: { title: "A new message", body: "Open Chips to read it." },
22871
+ /** A join request for its maker or an owner (ADR 0122). */
22872
+ join: { title: "Something asks to join", body: "Check its code, then allow it or not." },
22873
+ /** The referee paused agents talking among themselves (ADR 0097). */
22874
+ held: { title: "Chips paused the agents", body: "Open the space to let them carry on." },
22875
+ warning: { title: "The agents need a look", body: "They have been talking among themselves." },
22876
+ /** A guest's ask to go direct, and its answers (ADR 0211). */
22877
+ directAsked: {
22878
+ title: "A guest wants to connect directly",
22879
+ body: "Share your server with them in Tailscale."
22880
+ },
22881
+ directShared: { title: "Your server is shared with you", body: "Open Chips to go direct." },
22882
+ directDone: {
22883
+ title: "Connected directly",
22884
+ body: "A guest you shared your server with is direct now."
22885
+ },
22886
+ /** An owner is turning the relay off (ADR 0211, Phase 4). */
22887
+ relayOff: { title: "The relay is going off", body: "Go direct to keep reaching the server." }
22888
+ };
22889
+ var KNOWN = new Set(Object.values(PUSH_WORDS).map((words4) => JSON.stringify([words4.title, words4.body, "categoryId" in words4 ? words4.categoryId : null])));
22846
22890
 
22847
22891
  // node_modules/@chipschat/harness/dist/asks.js
22848
22892
  var Asks = class {
@@ -22877,10 +22921,7 @@ var Asks = class {
22877
22921
  const from = event["from"];
22878
22922
  if (!this.listener.listening() || from?.kind !== "person")
22879
22923
  return false;
22880
- this.hand(spaceId, room, {
22881
- messageId: String(event["message_id"]),
22882
- text: String(event["text"] ?? "")
22883
- });
22924
+ this.hand(spaceId, room, { messageId: String(event["message_id"]), text: String(event["text"] ?? "") }, event);
22884
22925
  return true;
22885
22926
  }
22886
22927
  /**
@@ -22916,11 +22957,42 @@ var Asks = class {
22916
22957
  this.rooms.set(spaceId, room);
22917
22958
  return room;
22918
22959
  }
22919
- hand(spaceId, room, first) {
22960
+ hand(spaceId, room, first, message) {
22920
22961
  room.first = first.messageId;
22921
- this.listener.hand({ spaceId, askedBy: room.askedBy, firstMessage: first });
22962
+ this.listener.hand({
22963
+ spaceId,
22964
+ askedBy: room.askedBy,
22965
+ firstMessage: first,
22966
+ ...message === void 0 ? {} : { message }
22967
+ });
22922
22968
  }
22923
22969
  };
22970
+ function firstTurnOf(asked, agentId2) {
22971
+ const { message } = asked;
22972
+ if (message === void 0)
22973
+ return void 0;
22974
+ const room = message.room;
22975
+ const notes = room?.notes ?? {};
22976
+ const [place, ...more] = Object.keys(notes);
22977
+ if (room === void 0 || place === void 0 || more.length > 0) {
22978
+ return { ...message, for: [agentId2] };
22979
+ }
22980
+ const placed = (each) => each.participant_id === place ? { ...each, participant_id: agentId2 } : each;
22981
+ const note = notes[place];
22982
+ const rules = room.rules?.[place];
22983
+ return {
22984
+ ...message,
22985
+ for: [agentId2],
22986
+ room: {
22987
+ ...room,
22988
+ members: room.members.map(placed),
22989
+ notes: note === void 0 ? {} : { [agentId2]: note },
22990
+ ...room.rules === void 0 ? {} : { rules: rules === void 0 ? {} : { [agentId2]: rules } },
22991
+ ...room.working === void 0 ? {} : { working: room.working.map(placed) },
22992
+ ...room.idle === void 0 ? {} : { idle: room.idle.map(placed) }
22993
+ }
22994
+ };
22995
+ }
22924
22996
  function firstWords(history) {
22925
22997
  for (const event of history) {
22926
22998
  const actor2 = event["actor"];
@@ -22931,6 +23003,10 @@ function firstWords(history) {
22931
23003
  return void 0;
22932
23004
  }
22933
23005
 
23006
+ // node_modules/@chipschat/harness/dist/connect.js
23007
+ import { readFile as readFile2 } from "node:fs/promises";
23008
+ import { basename } from "node:path";
23009
+
22934
23010
  // node_modules/@chipschat/harness/dist/events.js
22935
23011
  var Emitter = class {
22936
23012
  handlers = /* @__PURE__ */ new Map();
@@ -26532,6 +26608,8 @@ var Bridge = class {
26532
26608
  wake;
26533
26609
  /** A person's Restart under way: nothing is said of how it is meanwhile (Chips ADR 0094). */
26534
26610
  restarting;
26611
+ /** Restarts begun, so a health check asked before one, and answered after, is let go. */
26612
+ restarts = 0;
26535
26613
  /** Why OpenCode's server isn't there, where the bridge knows more than that it doesn't answer. */
26536
26614
  why;
26537
26615
  /** The files OpenCode builds each agent from, where the bridge knows each agent's folder. */
@@ -26587,6 +26665,7 @@ var Bridge = class {
26587
26665
  * doesn't run the server, which never says it hears restarts.
26588
26666
  */
26589
26667
  restart() {
26668
+ if (this.restarting === void 0) this.restarts += 1;
26590
26669
  this.restarting ??= (async () => {
26591
26670
  try {
26592
26671
  await this.restartServer();
@@ -26648,12 +26727,14 @@ var Bridge = class {
26648
26727
  }
26649
26728
  /**
26650
26729
  * Trouble while the server doesn't answer, and fine once it does (ADR 0083). Nothing while a
26651
- * restart is under way: its end says (ADR 0094).
26730
+ * restart is under way: its end says (ADR 0094). Nor an answer to a check asked before a restart
26731
+ * began, even one over by now: it is of the server before, and a failed restart's words would go.
26652
26732
  */
26653
26733
  async sayHowItIs() {
26654
26734
  if (this.restarting !== void 0) return;
26735
+ const restarts = this.restarts;
26655
26736
  const up = await this.options.opencode.healthy();
26656
- if (this.restarting !== void 0) return;
26737
+ if (this.restarts !== restarts) return;
26657
26738
  if (up) this.why = void 0;
26658
26739
  const chips2 = this.options.chips;
26659
26740
  await (up ? chips2.reportOk() : chips2.reportTrouble(this.why ?? "OpenCode isn't answering")).catch(() => void 0);
@@ -26723,7 +26804,7 @@ var Bridge = class {
26723
26804
  await this.sendContexts();
26724
26805
  const context = await chips2.roomContext(spaceId, { limit: 20 }).catch(() => void 0);
26725
26806
  const said = context?.lines.find((line) => line.message_id === firstMessage.messageId)?.from;
26726
- const message = {
26807
+ const message = firstTurnOf(asked, agent.agentId) ?? {
26727
26808
  type: "message.new",
26728
26809
  space_id: spaceId,
26729
26810
  message_id: firstMessage.messageId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chipschat/opencode",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "OpenCode as a Chips harness, on its V2 server (opencode serve): each OpenCode agent a Chips agent, each room an OpenCode session.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -33,9 +33,9 @@
33
33
  "release": "npm run build && npm test && npm pack"
34
34
  },
35
35
  "devDependencies": {
36
- "@chipschat/conformance": "1.0.1",
37
- "@chipschat/harness": "1.0.1",
38
- "@chipschat/protocol": "1.0.1",
36
+ "@chipschat/conformance": "1.0.2",
37
+ "@chipschat/harness": "1.0.2",
38
+ "@chipschat/protocol": "1.0.2",
39
39
  "@types/node": "22.19.0",
40
40
  "esbuild": "0.27.7",
41
41
  "tsx": "4.21.0",