@dashup/connector 0.1.17 → 0.1.18
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/README.md +2 -2
- package/dist/index.js +79 -14
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -47,9 +47,9 @@ Only an explicit Queue reply starts a temporary official app-server helper to in
|
|
|
47
47
|
|
|
48
48
|
Delivery requires that exact typed client-message ID in the original thread's native history database. A response receipt requires a later native assistant item in the same turn; it does not mean the agent finished. Receipts remain encrypted through the ordinary Dashup relay. History is read on request; the phone asks again while a thread is open and its session changes. Native approvals owned by the private-stdio process remain unsupported and require its original UI. Queue text never substitutes for a native approval.
|
|
49
49
|
|
|
50
|
-
Each thread shows what its agent's own record says it last ran with. A Claude Code session shows the model of its newest reply and, where that model takes them, fast mode and ultracode; the choices and their names are the models the session's own Claude Code binary offers hosts in its initialize answer, or `claude`'s where the system does not name the binary. A Codex thread shows the model and reasoning effort of its newest turn and, where the model has the priority tier, fast mode, named from Codex's own `models_cache.json`. A setting an agent records only when it changes, such as ultracode or Codex's tier, is searched for however far back it lies. A saved thread carries these, without choices, only in its own published state, never in a project's snapshot.
|
|
50
|
+
Each thread shows what its agent's own record says it last ran with. A Claude Code session shows the model of its newest reply and, where that model takes them, fast mode and ultracode; the choices and their names are the models the session's own Claude Code binary offers hosts in its initialize answer, or `claude`'s where the system does not name the binary. A Codex thread shows the model and reasoning effort of its newest turn and, where the model has the priority tier, fast mode, named from Codex's own `models_cache.json`. An OpenCode session shows the model and agent OpenCode keeps on the session (`/api/session`), among the models and primary agents it lists for the folder. A setting an agent records only when it changes, such as ultracode or Codex's tier, is searched for however far back it lies. A saved thread carries these, without choices, only in its own published state, never in a project's snapshot.
|
|
51
51
|
|
|
52
|
-
The phone changes a running session's settings: through the Claude plugin with Claude Code's own `/model`, `/fast` and `/effort ultracode` commands; in a Claude session the phone started, with control requests at the start of each turn;
|
|
52
|
+
The phone changes a running session's settings: through the Claude plugin with Claude Code's own `/model`, `/fast` and `/effort ultracode` commands; in a Claude session the phone started, with control requests at the start of each turn; in a Codex thread the connector holds, with the next `turn/start` it sends; and in an OpenCode session, on the session itself, so the phone's messages go in what it runs with. An agent records a change when its next turn starts, so it shows from the next reply. A change expires with other commands after 60 seconds.
|
|
53
53
|
|
|
54
54
|
Stop interrupts the running turn through each live interface: OpenCode's session abort, Codex `turn/interrupt`, the AHP client's turn cancellation, ACP `session/cancel`, and the Claude Code plugin's turn abort. It refuses when nothing is running and expires with other commands after 60 seconds, so a late stop cannot end a newer turn.
|
|
55
55
|
|
package/dist/index.js
CHANGED
|
@@ -4048,7 +4048,7 @@ import * as ui from "@clack/prompts";
|
|
|
4048
4048
|
import { z } from "zod";
|
|
4049
4049
|
|
|
4050
4050
|
// package.json
|
|
4051
|
-
var version = "0.1.
|
|
4051
|
+
var version = "0.1.18";
|
|
4052
4052
|
|
|
4053
4053
|
// src/pair.ts
|
|
4054
4054
|
var Invitation = z.object({
|
|
@@ -18287,7 +18287,14 @@ ${NO_PREVIEW}`;
|
|
|
18287
18287
|
...change2 ? { change: change2 } : {}
|
|
18288
18288
|
};
|
|
18289
18289
|
}
|
|
18290
|
-
function promptContext(history) {
|
|
18290
|
+
function promptContext(history, session) {
|
|
18291
|
+
const current = session?.model;
|
|
18292
|
+
if (typeof session?.agent === "string" && typeof current?.providerID === "string" && typeof current.id === "string")
|
|
18293
|
+
return {
|
|
18294
|
+
agent: session.agent,
|
|
18295
|
+
model: { providerID: current.providerID, modelID: current.id },
|
|
18296
|
+
...typeof current.variant === "string" ? { variant: current.variant } : {}
|
|
18297
|
+
};
|
|
18291
18298
|
if (!Array.isArray(history)) throw new Error("OpenCode session context is unavailable");
|
|
18292
18299
|
const user = [...history].reverse().find((entry) => entry?.info?.role === "user")?.info;
|
|
18293
18300
|
if (!user) return {};
|
|
@@ -18301,6 +18308,26 @@ function promptContext(history) {
|
|
|
18301
18308
|
...variant === void 0 ? {} : { variant }
|
|
18302
18309
|
};
|
|
18303
18310
|
}
|
|
18311
|
+
function sessionOptions(models2, agents, session) {
|
|
18312
|
+
const current = session?.model;
|
|
18313
|
+
if (typeof current?.providerID !== "string" || typeof current.id !== "string") return [];
|
|
18314
|
+
const value2 = `${current.providerID}/${current.id}`;
|
|
18315
|
+
const agent = typeof session?.agent === "string" ? session.agent : void 0;
|
|
18316
|
+
const listed = (Array.isArray(models2) ? models2 : []).filter((model) => typeof model?.providerID === "string" && typeof model.id === "string").map((model) => ({
|
|
18317
|
+
value: `${model.providerID}/${model.id}`,
|
|
18318
|
+
name: String(model.name ?? model.id)
|
|
18319
|
+
}));
|
|
18320
|
+
const primary = (Array.isArray(agents) ? agents : []).filter(
|
|
18321
|
+
(item) => typeof item?.id === "string" && item.mode !== "subagent" && !item.hidden
|
|
18322
|
+
).map((item) => ({ value: String(item.id), name: String(item.name ?? item.id) }));
|
|
18323
|
+
if (!listed.some((choice) => choice.value === value2)) listed.push({ value: value2, name: current.id });
|
|
18324
|
+
if (agent && !primary.some((choice) => choice.value === agent))
|
|
18325
|
+
primary.push({ value: agent, name: agent });
|
|
18326
|
+
return [
|
|
18327
|
+
{ id: "model", name: "Model", value: value2, choices: listed },
|
|
18328
|
+
...agent ? [{ id: "agent", name: "Agent", value: agent, choices: primary }] : []
|
|
18329
|
+
];
|
|
18330
|
+
}
|
|
18304
18331
|
var Server = class {
|
|
18305
18332
|
constructor(endpoint, changed) {
|
|
18306
18333
|
this.endpoint = endpoint;
|
|
@@ -18313,6 +18340,8 @@ var Server = class {
|
|
|
18313
18340
|
notify;
|
|
18314
18341
|
stopped = false;
|
|
18315
18342
|
requests = /* @__PURE__ */ new Map();
|
|
18343
|
+
// The models and agents OpenCode lists for each folder, asked once while it answers.
|
|
18344
|
+
catalogs = /* @__PURE__ */ new Map();
|
|
18316
18345
|
headers(directory2) {
|
|
18317
18346
|
return {
|
|
18318
18347
|
...this.endpoint.authorization ? { Authorization: this.endpoint.authorization } : {},
|
|
@@ -18347,12 +18376,29 @@ var Server = class {
|
|
|
18347
18376
|
this.requests.set(id, pending);
|
|
18348
18377
|
return pending;
|
|
18349
18378
|
}
|
|
18350
|
-
|
|
18379
|
+
catalog(cwd) {
|
|
18380
|
+
let known = this.catalogs.get(cwd);
|
|
18381
|
+
if (!known) {
|
|
18382
|
+
known = Promise.all([
|
|
18383
|
+
this.request("/api/model", cwd).then((listed) => listed?.data),
|
|
18384
|
+
this.request("/api/agent", cwd).then((listed) => listed?.data)
|
|
18385
|
+
]).catch(() => {
|
|
18386
|
+
this.catalogs.delete(cwd);
|
|
18387
|
+
return [[], []];
|
|
18388
|
+
});
|
|
18389
|
+
this.catalogs.set(cwd, known);
|
|
18390
|
+
}
|
|
18391
|
+
return known;
|
|
18392
|
+
}
|
|
18393
|
+
// A message to one of this folder's sessions, in the agent and model it runs with; a new
|
|
18351
18394
|
// session takes OpenCode's defaults.
|
|
18352
18395
|
async prompt(id, cwd, text3) {
|
|
18353
|
-
const existing = await
|
|
18396
|
+
const [existing, session] = await Promise.all([
|
|
18397
|
+
this.request(`/session/${encodeURIComponent(id)}/message?limit=200`, cwd),
|
|
18398
|
+
this.request(`/api/session/${encodeURIComponent(id)}`, cwd).catch(() => void 0)
|
|
18399
|
+
]);
|
|
18354
18400
|
await this.request(`/session/${encodeURIComponent(id)}/prompt_async`, cwd, {
|
|
18355
|
-
...promptContext(existing),
|
|
18401
|
+
...promptContext(existing, session?.data),
|
|
18356
18402
|
parts: [{ type: "text", text: text3 }]
|
|
18357
18403
|
});
|
|
18358
18404
|
this.changed();
|
|
@@ -18382,11 +18428,16 @@ var Server = class {
|
|
|
18382
18428
|
state = Promise.all([
|
|
18383
18429
|
this.request("/session/status", cwd),
|
|
18384
18430
|
this.request("/permission", cwd).catch(() => []),
|
|
18385
|
-
this.request("/question", cwd).catch(() => [])
|
|
18431
|
+
this.request("/question", cwd).catch(() => []),
|
|
18432
|
+
this.request(`/api/session?limit=${MAX_SESSIONS4}`, cwd).then(
|
|
18433
|
+
(listed) => Array.isArray(listed?.data) ? listed.data : [],
|
|
18434
|
+
() => []
|
|
18435
|
+
),
|
|
18436
|
+
this.catalog(cwd)
|
|
18386
18437
|
]);
|
|
18387
18438
|
states.set(cwd, state);
|
|
18388
18439
|
}
|
|
18389
|
-
const [history, [status2, permissions, questions]] = await Promise.all([
|
|
18440
|
+
const [history, [status2, permissions, questions, settings, [models2, agents]]] = await Promise.all([
|
|
18390
18441
|
this.request(`/session/${encodeURIComponent(id)}/message?limit=200`, cwd),
|
|
18391
18442
|
state
|
|
18392
18443
|
]);
|
|
@@ -18396,6 +18447,7 @@ var Server = class {
|
|
|
18396
18447
|
const asks = Array.isArray(questions) ? questions.filter(
|
|
18397
18448
|
(question) => question?.sessionID === id && typeof question.id === "string"
|
|
18398
18449
|
) : [];
|
|
18450
|
+
const current = settings.find((item) => item?.id === id);
|
|
18399
18451
|
const approvals = pending.map((permission) => permissionApproval(permission, history, cwd));
|
|
18400
18452
|
for (const question of asks)
|
|
18401
18453
|
approvals.push(
|
|
@@ -18416,8 +18468,8 @@ var Server = class {
|
|
|
18416
18468
|
approvals,
|
|
18417
18469
|
stop: (requestId) => this.once(requestId, async () => {
|
|
18418
18470
|
if (this.stopped) throw new Error("OpenCode is disconnected");
|
|
18419
|
-
const
|
|
18420
|
-
if (!["busy", "retry"].includes(
|
|
18471
|
+
const current2 = await this.request("/session/status", cwd);
|
|
18472
|
+
if (!["busy", "retry"].includes(current2?.[id]?.type))
|
|
18421
18473
|
throw new Error("Nothing is running in this OpenCode session");
|
|
18422
18474
|
await this.request(`/session/${encodeURIComponent(id)}/abort`, cwd, {});
|
|
18423
18475
|
this.changed();
|
|
@@ -18434,19 +18486,32 @@ var Server = class {
|
|
|
18434
18486
|
if (Array.isArray(existing) && existing.some((entry) => entry?.info?.id === messageID))
|
|
18435
18487
|
return;
|
|
18436
18488
|
await this.request(`/session/${encodeURIComponent(id)}/prompt_async`, cwd, {
|
|
18437
|
-
...promptContext(existing),
|
|
18489
|
+
...promptContext(existing, current),
|
|
18438
18490
|
messageID,
|
|
18439
18491
|
parts: [{ type: "text", text: text3 }]
|
|
18440
18492
|
});
|
|
18441
18493
|
this.changed();
|
|
18442
18494
|
}),
|
|
18495
|
+
options: () => sessionOptions(models2, agents, current),
|
|
18496
|
+
// OpenCode keeps the model, as `provider/model`, and the agent on the session.
|
|
18497
|
+
configure: (requestId, option2, value2) => this.once(requestId, async () => {
|
|
18498
|
+
if (this.stopped) throw new Error("OpenCode is disconnected");
|
|
18499
|
+
const chosen = String(value2);
|
|
18500
|
+
const split = chosen.indexOf("/");
|
|
18501
|
+
await this.request(
|
|
18502
|
+
`/api/session/${encodeURIComponent(id)}/${option2}`,
|
|
18503
|
+
cwd,
|
|
18504
|
+
option2 === "model" ? { model: { providerID: chosen.slice(0, split), id: chosen.slice(split + 1) } } : { agent: chosen }
|
|
18505
|
+
);
|
|
18506
|
+
this.changed();
|
|
18507
|
+
}),
|
|
18443
18508
|
approve: approvals.some((approval2) => approval2.choices.length) ? (requestId, approvalId, reply) => this.once(requestId, async () => {
|
|
18444
18509
|
if (this.stopped) throw new Error("OpenCode is disconnected");
|
|
18445
18510
|
const choice = "choice" in reply ? reply.choice : void 0;
|
|
18446
18511
|
if (approvalId.startsWith("question:")) {
|
|
18447
18512
|
const requestID = approvalId.slice("question:".length);
|
|
18448
|
-
const
|
|
18449
|
-
if (!Array.isArray(
|
|
18513
|
+
const current2 = await this.request("/question", cwd);
|
|
18514
|
+
if (!Array.isArray(current2) || !current2.some(
|
|
18450
18515
|
(value2) => value2?.id === requestID && value2.sessionID === id
|
|
18451
18516
|
))
|
|
18452
18517
|
throw new Error("Question is no longer pending");
|
|
@@ -18456,8 +18521,8 @@ var Server = class {
|
|
|
18456
18521
|
"answers" in reply ? { answers: reply.answers } : {}
|
|
18457
18522
|
);
|
|
18458
18523
|
} else {
|
|
18459
|
-
const
|
|
18460
|
-
const permission = Array.isArray(
|
|
18524
|
+
const current2 = await this.request("/permission", cwd);
|
|
18525
|
+
const permission = Array.isArray(current2) ? current2.find(
|
|
18461
18526
|
(value2) => value2?.id === approvalId && value2.sessionID === id
|
|
18462
18527
|
) : void 0;
|
|
18463
18528
|
if (!PERMISSION_CHOICES.some((value2) => value2.id === choice) || !permission)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashup/connector",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dashup": "dist/index.js"
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"tsup": "^8.5.1",
|
|
31
31
|
"tsx": "^4.22.4",
|
|
32
32
|
"typescript": "^5.9.3",
|
|
33
|
+
"@dashup/models": "0.1.0",
|
|
33
34
|
"@dashup/protocol": "0.1.0",
|
|
35
|
+
"@dashup/typescript-config": "0.0.0",
|
|
34
36
|
"@parcae/lynx": "0.1.0",
|
|
35
|
-
"@
|
|
36
|
-
"@parcae/sdk": "0.8.1",
|
|
37
|
-
"@dashup/typescript-config": "0.0.0"
|
|
37
|
+
"@parcae/sdk": "0.8.1"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"dashup": "tsx src/index.ts",
|