offsite 0.0.88 → 0.0.90

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.
@@ -12,7 +12,7 @@ import { formatWithOptions, promisify } from "node:util";
12
12
  import { Command } from "@commander-js/extra-typings";
13
13
  import { execFile, spawn, spawnSync } from "node:child_process";
14
14
  import readline from "node:readline";
15
- import { lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rm, rmdir, stat, writeFile } from "node:fs/promises";
15
+ import fs, { lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rm, rmdir, stat, writeFile } from "node:fs/promises";
16
16
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
17
17
  import { OpenCode, isSessionNotFoundError } from "@opencode/client";
18
18
  import { ensure, headers } from "@opencode/client/service";
@@ -28,6 +28,7 @@ import webPush from "web-push";
28
28
  import dns from "node:dns";
29
29
  import { BlockList, isIP } from "node:net";
30
30
  import { CookieJar, getPublicSuffix } from "tough-cookie";
31
+ import { ping, text as text$1, workflows } from "@oiper/desktop";
31
32
  import { spawn as spawn$1 } from "@lydell/node-pty";
32
33
  import { once } from "node:events";
33
34
  import https from "node:https";
@@ -1175,7 +1176,8 @@ const configSchema = z.strictObject({
1175
1176
  ]).default("offsite"),
1176
1177
  shellIntegration: z.boolean().default(true)
1177
1178
  }).prefault({})
1178
- }).prefault({})
1179
+ }).prefault({}),
1180
+ dictation: z.strictObject({ workflowId: z.string().nullable().default(null) }).prefault({})
1179
1181
  });
1180
1182
  const defaults$1 = configSchema.parse({});
1181
1183
  function platform() {
@@ -2202,8 +2204,8 @@ function toolItems(base, tool) {
2202
2204
  case "shell": return [{
2203
2205
  ...base,
2204
2206
  kind: "command",
2205
- command: text$2(input.command),
2206
- description: text$2(input.description),
2207
+ command: text$3(input.command),
2208
+ description: text$3(input.description),
2207
2209
  output,
2208
2210
  status,
2209
2211
  background: null
@@ -2211,10 +2213,10 @@ function toolItems(base, tool) {
2211
2213
  case "edit": return [{
2212
2214
  ...base,
2213
2215
  kind: "file_change",
2214
- path: text$2(input.path ?? input.filePath),
2216
+ path: text$3(input.path ?? input.filePath),
2215
2217
  diffs: [{
2216
- before: text$2(input.oldString),
2217
- after: text$2(input.newString)
2218
+ before: text$3(input.oldString),
2219
+ after: text$3(input.newString)
2218
2220
  }],
2219
2221
  output,
2220
2222
  status
@@ -2222,10 +2224,10 @@ function toolItems(base, tool) {
2222
2224
  case "write": return [{
2223
2225
  ...base,
2224
2226
  kind: "file_change",
2225
- path: text$2(input.path ?? input.filePath),
2227
+ path: text$3(input.path ?? input.filePath),
2226
2228
  diffs: [{
2227
2229
  before: "",
2228
- after: text$2(input.content)
2230
+ after: text$3(input.content)
2229
2231
  }],
2230
2232
  output,
2231
2233
  status
@@ -2237,8 +2239,8 @@ function toolItems(base, tool) {
2237
2239
  ...base,
2238
2240
  id: `${base.id}:${index}`,
2239
2241
  kind: "file_change",
2240
- path: text$2(record(file).file),
2241
- diffs: hunks(text$2(record(file).patch)),
2242
+ path: text$3(record(file).file),
2243
+ diffs: hunks(text$3(record(file).patch)),
2242
2244
  output,
2243
2245
  status
2244
2246
  }));
@@ -2246,16 +2248,16 @@ function toolItems(base, tool) {
2246
2248
  ...base,
2247
2249
  kind: "todo_list",
2248
2250
  steps: list$1(input.todos).map((todo) => ({
2249
- text: text$2(record(todo).content),
2250
- status: todoStatuses$1[text$2(record(todo).status)] ?? "pending"
2251
+ text: text$3(record(todo).content),
2252
+ status: todoStatuses$1[text$3(record(todo).status)] ?? "pending"
2251
2253
  }))
2252
2254
  }];
2253
2255
  case "subagent":
2254
2256
  case "task": return [{
2255
2257
  ...base,
2256
2258
  kind: "subagent",
2257
- agent: text$2(input.agent ?? input.subagent_type) || "Agent",
2258
- description: text$2(input.description),
2259
+ agent: text$3(input.agent ?? input.subagent_type) || "Agent",
2260
+ description: text$3(input.description),
2259
2261
  agentId: typeof metadata.sessionID === "string" ? metadata.sessionID : null,
2260
2262
  status
2261
2263
  }];
@@ -2263,20 +2265,20 @@ function toolItems(base, tool) {
2263
2265
  case "websearch": return [{
2264
2266
  ...base,
2265
2267
  kind: "web_search",
2266
- query: tool.name === "websearch" ? text$2(input.query) : null,
2267
- url: tool.name === "webfetch" ? text$2(input.url) : null,
2268
+ query: tool.name === "websearch" ? text$3(input.query) : null,
2269
+ url: tool.name === "webfetch" ? text$3(input.url) : null,
2268
2270
  results: [],
2269
2271
  output,
2270
2272
  status
2271
2273
  }];
2272
2274
  case "question": {
2273
2275
  const questions = list$1(input.questions).map((item) => ({
2274
- question: text$2(record(item).question),
2275
- header: text$2(record(item).header),
2276
+ question: text$3(record(item).question),
2277
+ header: text$3(record(item).header),
2276
2278
  multiSelect: record(item).multiple === true,
2277
2279
  options: list$1(record(item).options).map((option) => ({
2278
- label: text$2(record(option).label),
2279
- description: text$2(record(option).description)
2280
+ label: text$3(record(option).label),
2281
+ description: text$3(record(option).description)
2280
2282
  }))
2281
2283
  }));
2282
2284
  const answers = metadata.answers;
@@ -2284,14 +2286,14 @@ function toolItems(base, tool) {
2284
2286
  ...base,
2285
2287
  kind: "question",
2286
2288
  questions,
2287
- answers: Array.isArray(answers) ? Object.fromEntries(questions.map((question, index) => [question.question, list$1(answers[index]).map(text$2).join(", ")])) : null,
2289
+ answers: Array.isArray(answers) ? Object.fromEntries(questions.map((question, index) => [question.question, list$1(answers[index]).map(text$3).join(", ")])) : null,
2288
2290
  status
2289
2291
  }];
2290
2292
  }
2291
2293
  case "skill": return [{
2292
2294
  ...base,
2293
2295
  kind: "skill",
2294
- skill: text$2(input.id),
2296
+ skill: text$3(input.id),
2295
2297
  output,
2296
2298
  status
2297
2299
  }];
@@ -2332,7 +2334,7 @@ function optionValue(options, label) {
2332
2334
  function contentText(content) {
2333
2335
  return content.map((block) => block.type === "text" ? block.text : block.uri).join("\n");
2334
2336
  }
2335
- function text$2(value) {
2337
+ function text$3(value) {
2336
2338
  return typeof value === "string" ? value : "";
2337
2339
  }
2338
2340
  function list$1(value) {
@@ -5319,10 +5321,10 @@ function toItems(messages) {
5319
5321
  break;
5320
5322
  case "tool_use":
5321
5323
  if (block.name === "SendMessage") {
5322
- const owner = owners.get(text$1(block.input.to));
5324
+ const owner = owners.get(text$2(block.input.to));
5323
5325
  if (owner !== void 0) change(owner, { status: "running" });
5324
5326
  }
5325
- if (block.name === "TaskStop") stops.set(block.id, text$1(block.input.task_id));
5327
+ if (block.name === "TaskStop") stops.set(block.id, text$2(block.input.task_id));
5326
5328
  tools.set(block.id, items.length);
5327
5329
  items.push(toolItem(block, message.parent, message.time, (to) => {
5328
5330
  const owner = owners.get(to);
@@ -5413,7 +5415,7 @@ function toRequest(options) {
5413
5415
  case "ExitPlanMode": return {
5414
5416
  id: options.id,
5415
5417
  kind: "plan",
5416
- plan: text$1(options.input.plan)
5418
+ plan: text$2(options.input.plan)
5417
5419
  };
5418
5420
  default: return {
5419
5421
  id: options.id,
@@ -5441,8 +5443,8 @@ function toolItem(tool, parent, time, ownerOf) {
5441
5443
  case "PowerShell": return {
5442
5444
  ...base,
5443
5445
  kind: "command",
5444
- command: text$1(input.command),
5445
- description: text$1(input.description),
5446
+ command: text$2(input.command),
5447
+ description: text$2(input.description),
5446
5448
  output: "",
5447
5449
  status: "running",
5448
5450
  background: input.run_in_background === true ? {
@@ -5454,8 +5456,8 @@ function toolItem(tool, parent, time, ownerOf) {
5454
5456
  case "Monitor": return {
5455
5457
  ...base,
5456
5458
  kind: "command",
5457
- command: text$1(input.command) || (isRecord(input.ws) ? text$1(input.ws.url) : ""),
5458
- description: text$1(input.description),
5459
+ command: text$2(input.command) || (isRecord(input.ws) ? text$2(input.ws.url) : ""),
5460
+ description: text$2(input.description),
5459
5461
  output: "",
5460
5462
  status: "running",
5461
5463
  background: {
@@ -5467,10 +5469,10 @@ function toolItem(tool, parent, time, ownerOf) {
5467
5469
  case "Edit": return {
5468
5470
  ...base,
5469
5471
  kind: "file_change",
5470
- path: text$1(input.file_path),
5472
+ path: text$2(input.file_path),
5471
5473
  diffs: [{
5472
- before: text$1(input.old_string),
5473
- after: text$1(input.new_string)
5474
+ before: text$2(input.old_string),
5475
+ after: text$2(input.new_string)
5474
5476
  }],
5475
5477
  output: "",
5476
5478
  status: "running"
@@ -5478,7 +5480,7 @@ function toolItem(tool, parent, time, ownerOf) {
5478
5480
  case "MultiEdit": return {
5479
5481
  ...base,
5480
5482
  kind: "file_change",
5481
- path: text$1(input.file_path),
5483
+ path: text$2(input.file_path),
5482
5484
  diffs: input.edits.map((edit) => ({
5483
5485
  before: edit.old_string,
5484
5486
  after: edit.new_string
@@ -5489,10 +5491,10 @@ function toolItem(tool, parent, time, ownerOf) {
5489
5491
  case "Write": return {
5490
5492
  ...base,
5491
5493
  kind: "file_change",
5492
- path: text$1(input.file_path),
5494
+ path: text$2(input.file_path),
5493
5495
  diffs: [{
5494
5496
  before: "",
5495
- after: text$1(input.content)
5497
+ after: text$2(input.content)
5496
5498
  }],
5497
5499
  output: "",
5498
5500
  status: "running"
@@ -5500,7 +5502,7 @@ function toolItem(tool, parent, time, ownerOf) {
5500
5502
  case "NotebookEdit": return {
5501
5503
  ...base,
5502
5504
  kind: "file_change",
5503
- path: text$1(input.notebook_path),
5505
+ path: text$2(input.notebook_path),
5504
5506
  diffs: [],
5505
5507
  output: "",
5506
5508
  status: "running"
@@ -5509,7 +5511,7 @@ function toolItem(tool, parent, time, ownerOf) {
5509
5511
  ...base,
5510
5512
  kind: "web_search",
5511
5513
  query: null,
5512
- url: text$1(input.url),
5514
+ url: text$2(input.url),
5513
5515
  results: [],
5514
5516
  output: "",
5515
5517
  status: "running"
@@ -5517,7 +5519,7 @@ function toolItem(tool, parent, time, ownerOf) {
5517
5519
  case "WebSearch": return {
5518
5520
  ...base,
5519
5521
  kind: "web_search",
5520
- query: text$1(input.query),
5522
+ query: text$2(input.query),
5521
5523
  url: null,
5522
5524
  results: [],
5523
5525
  output: "",
@@ -5526,7 +5528,7 @@ function toolItem(tool, parent, time, ownerOf) {
5526
5528
  case "Skill": return {
5527
5529
  ...base,
5528
5530
  kind: "skill",
5529
- skill: text$1(input.skill),
5531
+ skill: text$2(input.skill),
5530
5532
  output: "",
5531
5533
  status: "running"
5532
5534
  };
@@ -5541,7 +5543,7 @@ function toolItem(tool, parent, time, ownerOf) {
5541
5543
  case "ExitPlanMode": return {
5542
5544
  ...base,
5543
5545
  kind: "plan",
5544
- plan: text$1(input.plan)
5546
+ plan: text$2(input.plan)
5545
5547
  };
5546
5548
  case "AskUserQuestion": return {
5547
5549
  ...base,
@@ -5552,23 +5554,23 @@ function toolItem(tool, parent, time, ownerOf) {
5552
5554
  };
5553
5555
  case "Agent":
5554
5556
  case "Task": {
5555
- const agent = text$1(input.subagent_type);
5557
+ const agent = text$2(input.subagent_type);
5556
5558
  return {
5557
5559
  ...base,
5558
5560
  kind: "subagent",
5559
5561
  agent: agent === "" ? "general-purpose" : agent,
5560
- description: text$1(input.description),
5562
+ description: text$2(input.description),
5561
5563
  agentId: null,
5562
5564
  status: "running"
5563
5565
  };
5564
5566
  }
5565
5567
  case "SendMessage": {
5566
- const summary = text$1(input.summary);
5568
+ const summary = text$2(input.summary);
5567
5569
  return {
5568
5570
  ...base,
5569
5571
  kind: "agent_message",
5570
- target: ownerOf(text$1(input.to)),
5571
- summary: summary === "" ? text$1(input.message).split("\n")[0] : summary,
5572
+ target: ownerOf(text$2(input.to)),
5573
+ summary: summary === "" ? text$2(input.message).split("\n")[0] : summary,
5572
5574
  status: "running"
5573
5575
  };
5574
5576
  }
@@ -5658,7 +5660,7 @@ function userText$1(value) {
5658
5660
  text: value
5659
5661
  };
5660
5662
  }
5661
- function text$1(value) {
5663
+ function text$2(value) {
5662
5664
  return typeof value === "string" ? value : "";
5663
5665
  }
5664
5666
  // src/lib/claude/history.ts
@@ -6315,6 +6317,26 @@ async function isLocalHost(hostname) {
6315
6317
  if (isIP(hostname) !== 0) return isPrivate(hostname);
6316
6318
  return (await dns.promises.lookup(hostname, { all: true })).some((item) => isPrivate(item.address));
6317
6319
  }
6320
+ // src/services/dictation.ts
6321
+ async function transcribe(audio) {
6322
+ const workflowId = readConfig().dictation.workflowId;
6323
+ if (workflowId === null) throw new Error("No OiPer workflow is chosen for dictation");
6324
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "offsite-dictation-"));
6325
+ try {
6326
+ const audioPath = path.join(dir, "dictation");
6327
+ await fs.writeFile(audioPath, audio);
6328
+ return (await text$1({
6329
+ audioPath,
6330
+ contentType: "audio/wav",
6331
+ workflowId
6332
+ })).text;
6333
+ } finally {
6334
+ await fs.rm(dir, {
6335
+ recursive: true,
6336
+ force: true
6337
+ });
6338
+ }
6339
+ }
6318
6340
  // src/services/runs.ts
6319
6341
  const locks = /* @__PURE__ */ new Map();
6320
6342
  const emptied = /* @__PURE__ */ new Set();
@@ -8284,6 +8306,9 @@ const handlers = {
8284
8306
  "files.media": (params, client) => linkProjectMedia(projectPath(params.projectId), params.path, client.device),
8285
8307
  "files.download": (params, client) => linkProjectDownload(projectPath(params.projectId), params.path, client.device),
8286
8308
  "files.upload": (params) => saveUpload(params.name, Buffer.from(params.data, "base64")),
8309
+ "dictation.transcribe": (params) => transcribe(Buffer.from(params.audio, "base64")),
8310
+ "dictation.ping": () => ping(),
8311
+ "dictation.workflows": () => workflows(),
8287
8312
  "files.browse": (_params, client) => linkBrowse(client.device, client.address),
8288
8313
  "browser.open": (params) => openSite(params.url, params.fromPage),
8289
8314
  "tasks.output": (params) => taskOutput(params.sessionId, params.path),