@dashup/connector 0.1.9 → 0.1.10

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.
Files changed (2) hide show
  1. package/dist/index.js +163 -23
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -2733,6 +2733,10 @@ var HISTORY_BATCH_ITEMS = 50;
2733
2733
  var HISTORY_BATCH_BYTES = HISTORY_PAGE_BYTES;
2734
2734
  var HISTORY_RECORD_BYTES = 32 * 1024;
2735
2735
  var HISTORY_RECORD_CIPHERTEXT_BYTES = HISTORY_RECORD_BYTES + 16;
2736
+ var OUTPUT_PREVIEW = { lines: 12, chars: 2e3 };
2737
+ var HISTORY_ATTACHMENTS = 16;
2738
+ var MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;
2739
+ var ATTACHMENT_NAME_CHARS = 100;
2736
2740
  var MESSAGE_ROLES = ["user", "assistant", "system", "tool"];
2737
2741
  var HARNESSES = {
2738
2742
  claude: "Claude Code",
@@ -2875,6 +2879,21 @@ function complexOverlapBytes(input, output) {
2875
2879
  if (overlapBytes(input, output) && input.byteOffset < output.byteOffset)
2876
2880
  throw new Error("complex overlap of input and output is not supported");
2877
2881
  }
2882
+ function concatBytes(...arrays) {
2883
+ let sum = 0;
2884
+ for (let i = 0; i < arrays.length; i++) {
2885
+ const a = arrays[i];
2886
+ abytes(a);
2887
+ sum += a.length;
2888
+ }
2889
+ const res = new Uint8Array(sum);
2890
+ for (let i = 0, pad = 0; i < arrays.length; i++) {
2891
+ const a = arrays[i];
2892
+ res.set(a, pad);
2893
+ pad += a.length;
2894
+ }
2895
+ return res;
2896
+ }
2878
2897
  function checkOpts(defaults, opts) {
2879
2898
  aobject(defaults, "defaults");
2880
2899
  aobject(opts, "opts");
@@ -3589,6 +3608,12 @@ function decryptContent(key, associatedData, sealed) {
3589
3608
  ).decrypt(ciphertextBytes(sealed.ciphertext));
3590
3609
  return JSON.parse(bytesToUtf8(cleartext));
3591
3610
  }
3611
+ var attachmentData = (pairing, id) => utf8ToBytes(JSON.stringify([PROTOCOL_VERSION, "attachment", pairing, id]));
3612
+ function sealAttachment(key, pairing, id, bytes, random) {
3613
+ const nonce = random(NONCE_BYTES);
3614
+ const cipher = xchacha20poly1305(hexToBytes(key), nonce, attachmentData(pairing, id));
3615
+ return concatBytes(nonce, cipher.encrypt(bytes));
3616
+ }
3592
3617
  var PAIRING_CODE = new RegExp(
3593
3618
  `^DASHUP:${PROTOCOL_VERSION}:([0-9A-F]{64}):([0-9A-F]{16}):([0-9A-F]{64}):(.+)$`
3594
3619
  );
@@ -3641,10 +3666,14 @@ function saveConfig(config2) {
3641
3666
  }
3642
3667
  }
3643
3668
  async function api(config2, path, body2, method = body2 ? "POST" : "GET") {
3669
+ const bytes = body2 instanceof Uint8Array;
3644
3670
  const response = await fetch(`${config2.api}/v1${path}`, {
3645
3671
  method,
3646
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${config2.secret}` },
3647
- body: body2 ? JSON.stringify(body2) : void 0
3672
+ headers: {
3673
+ "Content-Type": bytes ? "application/octet-stream" : "application/json",
3674
+ Authorization: `Bearer ${config2.secret}`
3675
+ },
3676
+ body: bytes ? new Uint8Array(body2) : body2 ? JSON.stringify(body2) : void 0
3648
3677
  });
3649
3678
  const value2 = await response.json();
3650
3679
  if (!response.ok || !value2.success)
@@ -4016,7 +4045,7 @@ import * as ui from "@clack/prompts";
4016
4045
  import { z } from "zod";
4017
4046
 
4018
4047
  // package.json
4019
- var version = "0.1.9";
4048
+ var version = "0.1.10";
4020
4049
 
4021
4050
  // src/pair.ts
4022
4051
  var Invitation = z.object({
@@ -4173,6 +4202,13 @@ function agentHarness(name) {
4173
4202
  if (/opencode/i.test(name)) return "opencode";
4174
4203
  return void 0;
4175
4204
  }
4205
+ var attached = (id, mime, data, name) => ({
4206
+ id,
4207
+ mime,
4208
+ bytes: Buffer.byteLength(data, "base64"),
4209
+ ...name ? { name: name.slice(-ATTACHMENT_NAME_CHARS) } : {},
4210
+ read: () => Buffer.from(data, "base64")
4211
+ });
4176
4212
  var MAX_PREVIEW = 64 * 1024;
4177
4213
  var NO_PREVIEW = "Review the full request on your computer before approving.";
4178
4214
 
@@ -4332,13 +4368,27 @@ function text(value2) {
4332
4368
  const part = object(value2);
4333
4369
  return part ? typeof part.text === "string" ? part.text : text(part.content) : "";
4334
4370
  }
4371
+ var DATA_URL = /^data:([^;,]+);base64,/;
4372
+ function attachments(id, content) {
4373
+ return list(content).flatMap((part, index) => {
4374
+ const key = `${id}:${index}`;
4375
+ const name = [part?.title, part?.filename].find((value2) => typeof value2 === "string");
4376
+ const source = object(part?.source);
4377
+ if (source?.type === "base64" && typeof source.data === "string")
4378
+ return [attached(key, String(source.media_type), source.data, name)];
4379
+ const url2 = String(part?.image_url ?? part?.url ?? "");
4380
+ const data = DATA_URL.exec(url2);
4381
+ return data ? [attached(key, data[1], url2.slice(data[0].length), name)] : [];
4382
+ });
4383
+ }
4335
4384
  function prose(id, role, content) {
4336
4385
  const value2 = text(
4337
4386
  Array.isArray(content) ? content.filter(
4338
4387
  (part) => typeof part === "string" || ["text", "input_text", "output_text"].includes(part?.type)
4339
4388
  ) : content
4340
4389
  );
4341
- return value2 ? [{ id, role, text: value2 }] : [];
4390
+ const files2 = attachments(id, content);
4391
+ return value2 || files2.length ? [{ id, role, text: value2, ...files2.length ? { attachments: files2 } : {} }] : [];
4342
4392
  }
4343
4393
  var SUMMARY_LIMIT = 200;
4344
4394
  var SUMMARY_FIELDS = [
@@ -4357,10 +4407,10 @@ var SUMMARY_FIELDS = [
4357
4407
  var PATCH_FILE = /^\*\*\* (Add|Update|Delete) File: (.+)$/gm;
4358
4408
  function describe(input) {
4359
4409
  const fields = object(input);
4360
- const named = SUMMARY_FIELDS.map((key) => fields?.[key]).find(
4410
+ const named2 = SUMMARY_FIELDS.map((key) => fields?.[key]).find(
4361
4411
  (value3) => typeof value3 === "string" && value3.trim() !== ""
4362
4412
  );
4363
- const value2 = typeof input === "string" ? input : named ?? (fields && Object.keys(fields).length ? JSON.stringify(fields) : "");
4413
+ const value2 = typeof input === "string" ? input : named2 ?? (fields && Object.keys(fields).length ? JSON.stringify(fields) : "");
4364
4414
  const paths = [...value2.matchAll(PATCH_FILE)].map((match) => match[2]).join(", ");
4365
4415
  const first = value2.split("\n").find((line) => line.trim());
4366
4416
  return (paths || first?.trim())?.slice(0, SUMMARY_LIMIT);
@@ -4378,9 +4428,10 @@ function added(path, content) {
4378
4428
  ...lines.map((line) => `+${line}`)
4379
4429
  ].join("\n");
4380
4430
  }
4431
+ var binary = (diff) => diff.slice(0, 8e3).includes("\0");
4381
4432
  function step(id, name, input, result) {
4382
4433
  const summary = describe(input);
4383
- const diff = result?.status === "ok" ? result.diff : void 0;
4434
+ const diff = result?.status === "ok" && result.diff && !binary(result.diff) ? result.diff : void 0;
4384
4435
  return {
4385
4436
  id,
4386
4437
  role: "tool",
@@ -4391,7 +4442,8 @@ function step(id, name, input, result) {
4391
4442
  ...result?.status ? { status: result.status } : {},
4392
4443
  ...result?.status && result.ms !== void 0 ? { ms: result.ms } : {},
4393
4444
  ...diff ? { diff: true } : {}
4394
- }
4445
+ },
4446
+ ...result?.attachments?.length ? { attachments: result.attachments } : {}
4395
4447
  };
4396
4448
  }
4397
4449
  var claudeHome = () => process.env.CLAUDE_CONFIG_DIR ?? join2(homedir2(), ".claude");
@@ -4447,16 +4499,18 @@ function claudeConversation(conversation, rows) {
4447
4499
  ...list(content).flatMap((part, position) => {
4448
4500
  if (part?.type !== "tool_use") return [];
4449
4501
  const result = results.get(part.id);
4502
+ const call = String(part.id ?? `${id}:${position}`);
4450
4503
  return [
4451
4504
  step(
4452
- String(part.id ?? `${id}:${position}`),
4505
+ call,
4453
4506
  part.name,
4454
4507
  part.input,
4455
4508
  result && {
4456
4509
  text: text(result.part.content),
4457
4510
  status: result.part.is_error ? "error" : "ok",
4458
4511
  ms: elapsed(row.timestamp, result.row.timestamp),
4459
- diff: claudeChange(object(result.row.toolUseResult))
4512
+ diff: claudeChange(object(result.row.toolUseResult)),
4513
+ attachments: attachments(call, result.part.content)
4460
4514
  }
4461
4515
  )
4462
4516
  ];
@@ -4471,7 +4525,7 @@ function claude(root, scan) {
4471
4525
  const latest = [...rows].reverse();
4472
4526
  const owner = rows.find((row) => typeof row.sessionId === "string" && canonical(row.cwd));
4473
4527
  if (!owner) return void 0;
4474
- const named = latest.find((row) => row.type === "custom-title" || row.type === "ai-title");
4528
+ const named2 = latest.find((row) => row.type === "custom-title" || row.type === "ai-title");
4475
4529
  const first = rows.find(
4476
4530
  (row) => row.type === "user" && !row.isMeta && !row.isSidechain && !injected(row.message?.content)
4477
4531
  );
@@ -4479,7 +4533,7 @@ function claude(root, scan) {
4479
4533
  id: String(owner.sessionId),
4480
4534
  cwd: canonical(owner.cwd),
4481
4535
  title: title(
4482
- named?.customTitle ?? named?.aiTitle ?? text(first?.message?.content),
4536
+ named2?.customTitle ?? named2?.aiTitle ?? text(first?.message?.content),
4483
4537
  "Claude Code thread"
4484
4538
  ),
4485
4539
  updatedAt: date(latest.find(claudeMessage)?.timestamp, stamp.mtimeMs)
@@ -4535,15 +4589,17 @@ function codexMessages(path) {
4535
4589
  const input = item.type === "function_call" ? parse(String(item.arguments)) ?? item.arguments : item.input;
4536
4590
  const output = outputs.get(item.call_id);
4537
4591
  const patch = item.name === "apply_patch" && typeof input === "string" ? input : "";
4592
+ const call = String(item.call_id ?? id);
4538
4593
  return [
4539
4594
  step(
4540
- String(item.call_id ?? id),
4595
+ call,
4541
4596
  item.name,
4542
4597
  input,
4543
4598
  output && {
4544
4599
  ...codexResult(text(output.payload.output)),
4545
4600
  ms: elapsed(row.timestamp, output.timestamp),
4546
- diff: patch && applyPatch(patch)
4601
+ diff: patch && applyPatch(patch),
4602
+ attachments: attachments(call, output.payload.output)
4547
4603
  }
4548
4604
  )
4549
4605
  ];
@@ -4625,6 +4681,10 @@ function openCodeParts(id, role, parts2) {
4625
4681
  const key = String(part.id ?? `${id}:${index}`);
4626
4682
  if (part.type === "text" && typeof part.text === "string")
4627
4683
  return [{ id: key, role, text: part.text }];
4684
+ if (part.type === "file") {
4685
+ const files2 = attachments(key, [part]);
4686
+ return files2.length ? [{ id: key, role, text: "", attachments: files2 }] : [];
4687
+ }
4628
4688
  if (part.type !== "tool") return [];
4629
4689
  const state = object(part.state) ?? {};
4630
4690
  const status2 = state.status === "completed" ? "ok" : state.status === "error" ? "error" : void 0;
@@ -4637,7 +4697,8 @@ function openCodeParts(id, role, parts2) {
4637
4697
  text: text(state.output ?? state.error),
4638
4698
  status: status2,
4639
4699
  ms: elapsed(state.time?.start, state.time?.end),
4640
- diff: openCodeChange(state)
4700
+ diff: openCodeChange(state),
4701
+ attachments: attachments(key, state.attachments)
4641
4702
  }
4642
4703
  )
4643
4704
  ];
@@ -5148,12 +5209,12 @@ var Discovery = class {
5148
5209
  }
5149
5210
  }
5150
5211
  }
5151
- read(thread, attached) {
5212
+ read(thread, attached2) {
5152
5213
  const location2 = this.locations.get(thread.id);
5153
5214
  if (!location2) throw new Error("Thread is no longer available");
5154
5215
  if (location2.history) return location2.history.read();
5155
5216
  if (location2.live) return location2.live.messages;
5156
- if (attached) return attached;
5217
+ if (attached2) return attached2;
5157
5218
  if (location2.editor === "vscode") {
5158
5219
  const state = chatSession(location2.path);
5159
5220
  return (state.requests ?? []).flatMap((request2, index) => [
@@ -16110,13 +16171,18 @@ import { createHmac as createHmac2, randomBytes as randomBytes3 } from "node:cry
16110
16171
  var ID = /^[a-f0-9]{64}$/;
16111
16172
  var ROLES = new Set(MESSAGE_ROLES);
16112
16173
  var ROUTING_FIELDS = ["pairing", "sender", "recipient", "project", "thread"];
16174
+ var MIME = /^[\w.+-]{1,64}\/[\w.+-]{1,64}$/;
16113
16175
  var TOOL_TEXT = 500;
16176
+ function validAttachment(value2) {
16177
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.id === "string" && ID.test(value2.id) && typeof value2.mime === "string" && MIME.test(value2.mime) && Number.isSafeInteger(value2.bytes) && value2.bytes >= 0 && (value2.name === void 0 || typeof value2.name === "string" && value2.name.length <= ATTACHMENT_NAME_CHARS);
16178
+ }
16114
16179
  function validTool(value2) {
16115
16180
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.name === "string" && value2.name.length <= TOOL_TEXT && (value2.summary === void 0 || typeof value2.summary === "string" && value2.summary.length <= TOOL_TEXT) && (value2.status === void 0 || value2.status === "ok" || value2.status === "error") && (value2.ms === void 0 || Number.isSafeInteger(value2.ms) && value2.ms >= 0) && (value2.diff === void 0 || typeof value2.diff === "boolean");
16116
16181
  }
16117
16182
  function validMessage(value2) {
16118
- return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.id === "string" && ID.test(value2.id) && ROLES.has(value2.role) && typeof value2.text === "string" && value2.text.length <= HISTORY_TEXT_CHARS && Number.isSafeInteger(value2.part) && Number.isSafeInteger(value2.parts) && value2.part >= 0 && value2.parts > value2.part && (value2.tool === void 0 || value2.part === 0 && validTool(value2.tool));
16183
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.id === "string" && ID.test(value2.id) && ROLES.has(value2.role) && typeof value2.text === "string" && value2.text.length <= HISTORY_TEXT_CHARS && Number.isSafeInteger(value2.part) && Number.isSafeInteger(value2.parts) && value2.part >= 0 && value2.parts > value2.part && (value2.tool === void 0 || value2.part === 0 && validTool(value2.tool)) && (value2.full === void 0 || value2.part === 0 && validAttachment(value2.full)) && (value2.attachments === void 0 || value2.part === 0 && Array.isArray(value2.attachments) && value2.attachments.length <= HISTORY_ATTACHMENTS && value2.attachments.every(validAttachment));
16119
16184
  }
16185
+ var preview = (text3) => text3.split("\n", OUTPUT_PREVIEW.lines).join("\n").slice(0, OUTPUT_PREVIEW.chars);
16120
16186
  function splitHistoryMessages(messages5, opaqueId2) {
16121
16187
  return messages5.flatMap((message) => {
16122
16188
  const text3 = [];
@@ -16135,7 +16201,9 @@ function splitHistoryMessages(messages5, opaqueId2) {
16135
16201
  text: part,
16136
16202
  part: index,
16137
16203
  parts: text3.length,
16138
- ...index === 0 && message.tool ? { tool: message.tool } : {}
16204
+ ...index === 0 && message.tool ? { tool: message.tool } : {},
16205
+ ...index === 0 && message.full ? { full: message.full } : {},
16206
+ ...index === 0 && message.attachments?.length ? { attachments: message.attachments } : {}
16139
16207
  }));
16140
16208
  });
16141
16209
  }
@@ -16177,7 +16245,21 @@ function sealHistory(key, routing, message, random) {
16177
16245
  var HISTORY_PATH = "/dashup/history";
16178
16246
  var HISTORY_KEPT = 300;
16179
16247
  var opaque = (key, value2) => createHmac2("sha256", Buffer.from(key, "hex")).update(JSON.stringify(value2)).digest("hex");
16180
- var historyMessages = (key, project, thread, messages5) => splitHistoryMessages(messages5, (id) => opaque(key, ["history-message", project, thread, id]));
16248
+ function historyMessages(key, project, thread, messages5) {
16249
+ const name = (attachment) => named(key, project, thread, attachment);
16250
+ return splitHistoryMessages(
16251
+ messages5.map((message) => {
16252
+ const { full, attachments: attachments2, ...rest } = kept(message);
16253
+ const files2 = attachments2?.map(name).filter(validAttachment).slice(0, HISTORY_ATTACHMENTS);
16254
+ return {
16255
+ ...rest,
16256
+ ...full ? { full: name(full) } : {},
16257
+ ...files2?.length ? { attachments: files2 } : {}
16258
+ };
16259
+ }),
16260
+ (id) => opaque(key, ["history-message", project, thread, id])
16261
+ );
16262
+ }
16181
16263
  var copy = (messages5) => new Map(
16182
16264
  messages5.slice(-HISTORY_PAGE_ITEMS).map((message) => [message.id, JSON.stringify(message)])
16183
16265
  );
@@ -16253,6 +16335,51 @@ async function publishHistory(config2, pair, project, thread, messages5) {
16253
16335
  throw new Error("The encrypted history snapshot was not published");
16254
16336
  return summary;
16255
16337
  }
16338
+ var ATTACHMENTS_PATH = "/dashup/attachments";
16339
+ var PASTED = new RegExp(
16340
+ `data:([\\w.+-]+/[\\w.+-]+);base64,([A-Za-z0-9+/]{${OUTPUT_PREVIEW.chars},}={0,2})`,
16341
+ "g"
16342
+ );
16343
+ function kept(message) {
16344
+ const files2 = [...message.attachments ?? []];
16345
+ const text3 = message.role === "tool" ? message.text : message.text.replace(PASTED, (_, mime, data, at) => {
16346
+ files2.push(attached(`${message.id}@${at}`, mime, data));
16347
+ return "";
16348
+ });
16349
+ const start = message.role === "tool" && !message.tool?.diff ? preview(text3) : text3;
16350
+ const full = start.length < text3.length ? {
16351
+ id: `${message.id}:full`,
16352
+ mime: "text/plain",
16353
+ bytes: Buffer.byteLength(text3),
16354
+ read: () => Buffer.from(text3)
16355
+ } : void 0;
16356
+ return {
16357
+ ...message,
16358
+ text: start,
16359
+ ...full ? { full } : {},
16360
+ ...files2.length ? { attachments: files2 } : {}
16361
+ };
16362
+ }
16363
+ var named = (key, project, thread, attachment) => ({
16364
+ id: opaque(key, ["history-attachment", project, thread, attachment.id, attachment.bytes]),
16365
+ mime: attachment.mime,
16366
+ bytes: attachment.bytes,
16367
+ ...attachment.name ? { name: attachment.name } : {}
16368
+ });
16369
+ var readable = (attachment) => "read" in attachment;
16370
+ async function shareAttachment(config2, pair, project, thread, messages5, id) {
16371
+ if (!activePair(config2, pair)) throw new Error("Pairing is no longer available");
16372
+ const key = config2.pairs[pair.id].key;
16373
+ const found = messages5.flatMap((message) => {
16374
+ const { full, attachments: attachments2 = [] } = kept(message);
16375
+ return full ? [full, ...attachments2] : attachments2;
16376
+ }).find((attachment) => named(key, project, thread, attachment).id === id);
16377
+ if (!found || !readable(found)) throw new Error("This attachment is no longer on your computer");
16378
+ if (found.bytes > MAX_ATTACHMENT_BYTES)
16379
+ throw new Error("This attachment is too large to open on your phone");
16380
+ const sealed = sealAttachment(key, pair.id, id, found.read(), randomBytes3);
16381
+ await api(config2, `${ATTACHMENTS_PATH}/${pair.id}/${id}`, sealed);
16382
+ }
16256
16383
 
16257
16384
  // src/harness/live.ts
16258
16385
  import { promisify as promisify5 } from "node:util";
@@ -17405,12 +17532,12 @@ var Host = class {
17405
17532
  for (const pending of Array.isArray(session.inputNeeded) ? session.inputNeeded : []) {
17406
17533
  if (pending.kind !== "toolConfirmation" || pending.chat !== item.resource || pending.toolCall?.status !== "pending-confirmation")
17407
17534
  continue;
17408
- const preview = confirmation(pending.toolCall);
17535
+ const preview2 = confirmation(pending.toolCall);
17409
17536
  approvals.push({
17410
17537
  id: pending.id,
17411
17538
  title: text2(pending.toolCall.confirmationTitle) || pending.toolCall.displayName || "Native agent approval",
17412
- detail: preview.detail,
17413
- choices: preview.choices.map(({ id: id2, label }) => ({ id: id2, label }))
17539
+ detail: preview2.detail,
17540
+ choices: preview2.choices.map(({ id: id2, label }) => ({ id: id2, label }))
17414
17541
  });
17415
17542
  }
17416
17543
  const id = `vscode-ahp:${createHash3("sha256").update(this.entry.root).digest("hex").slice(0, 16)}:${item.resource}`;
@@ -18542,6 +18669,7 @@ var Command = z2.object({
18542
18669
  z2.object({ kind: z2.literal("thread.queue"), text: z2.string().min(1).max(1e5) }).strict(),
18543
18670
  z2.object({ kind: z2.literal("thread.stop") }).strict(),
18544
18671
  z2.object({ kind: z2.literal("approval.respond"), approvalId: z2.string(), choice: z2.string() }).strict(),
18672
+ z2.object({ kind: z2.literal("attachment.read"), id: z2.string().regex(/^[a-f0-9]{64}$/) }).strict(),
18545
18673
  z2.object({
18546
18674
  kind: z2.literal("session.start"),
18547
18675
  harness: z2.enum(["claude", "codex", "opencode"]),
@@ -19195,6 +19323,18 @@ var Connector = class {
19195
19323
  });
19196
19324
  return this.thread(pair, project, thread, history);
19197
19325
  }
19326
+ case "attachment.read": {
19327
+ if (!thread) throw new Error("Thread not found");
19328
+ const messages5 = this.discovery.read(thread, this.attached(thread)?.messages);
19329
+ return shareAttachment(
19330
+ this.config,
19331
+ pair,
19332
+ project.id,
19333
+ thread.id,
19334
+ messages5,
19335
+ command2.action.id
19336
+ );
19337
+ }
19198
19338
  case "thread.send": {
19199
19339
  if (!thread || !thread.capabilities.send)
19200
19340
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashup/connector",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "dashup": "dist/index.js"
@@ -29,11 +29,11 @@
29
29
  "tsup": "^8.5.1",
30
30
  "tsx": "^4.22.4",
31
31
  "typescript": "^5.9.3",
32
- "@dashup/models": "0.1.0",
33
- "@dashup/protocol": "0.1.0",
34
32
  "@dashup/typescript-config": "0.0.0",
33
+ "@dashup/protocol": "0.1.0",
34
+ "@parcae/lynx": "0.1.0",
35
35
  "@parcae/sdk": "0.8.1",
36
- "@parcae/lynx": "0.1.0"
36
+ "@dashup/models": "0.1.0"
37
37
  },
38
38
  "scripts": {
39
39
  "dashup": "tsx src/index.ts",