pinomad 0.12.0 → 0.13.0
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/dist/{chunk-np4jd070.js → chunk-4fferbxw.js} +97 -29
- package/dist/{chunk-ksfxqd8s.js → chunk-53xv3fny.js} +241 -48
- package/dist/{chunk-nppgxh6c.js → chunk-563fnad9.js} +1 -1
- package/dist/{chunk-41q0saz0.js → chunk-6th9xv39.js} +4 -4
- package/dist/{chunk-aqj9wfmb.js → chunk-90g1cg9n.js} +1 -1
- package/dist/{chunk-mnmqyq7d.js → chunk-aapsc9g0.js} +42 -48
- package/dist/{chunk-5qf1grkk.js → chunk-d4tq62yr.js} +46 -11
- package/dist/{chunk-gg2dcqbg.js → chunk-d9mq5d46.js} +22 -7
- package/dist/{chunk-47ff1d1t.js → chunk-kmzzjv53.js} +51 -4
- package/dist/{chunk-agq4tn9r.js → chunk-m51mq8vh.js} +4 -4
- package/dist/{chunk-vqkb70d7.js → chunk-maqv34cs.js} +2 -2
- package/dist/{chunk-vx7dy07y.js → chunk-ra86wjp5.js} +4 -4
- package/dist/{chunk-7wj0jh3t.js → chunk-s0h7c7da.js} +1 -1
- package/dist/{chunk-42nqtx5r.js → chunk-sd640dt7.js} +6 -6
- package/dist/{chunk-jeqsdcj1.js → chunk-t6fw0wa9.js} +4 -4
- package/dist/{chunk-t5abqsva.js → chunk-wd7aracm.js} +17 -5
- package/dist/pinomad.js +12 -12
- package/package.json +12 -11
- package/web/assets/{core-DnpzcQzs.js → core-BHm2gdHL.js} +1 -1
- package/web/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/web/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/web/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/web/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/web/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/web/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/web/assets/{highlighted-diff-Dn5ifsvK.js → highlighted-diff-DrHvSLK9.js} +2 -2
- package/web/assets/{highlights-DnHv6NBM.js → highlights-1aLwssz-.js} +1 -1
- package/web/assets/{highlights-themes-CUdrlZk3.js → highlights-themes-C1p4pFYS.js} +1 -1
- package/web/assets/index-A_AUJoO6.css +1 -0
- package/web/assets/index-BafYMKiN.js +396 -0
- package/web/assets/{shiki-BuPP5HCg.js → shiki-BwyCm3kZ.js} +2 -2
- package/web/assets/{shiki-langs-FJk0v0Ga.js → shiki-langs-CMlALLSg.js} +1 -1
- package/web/assets/{stream-tokenizer-Bl6bisIa.js → stream-tokenizer-BlgIhw0y.js} +1 -1
- package/web/assets/{theming-themes-BL_CC-Mm.js → theming-themes-DDvoqEqT.js} +1 -1
- package/web/assets/{xterm-view-ZsuzJb2C.js → xterm-view-BnKOnF3C.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/index-BV0ecolo.css +0 -1
- package/web/assets/index-DNsTTgPE.js +0 -396
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
openHostSettings,
|
|
6
6
|
sameList,
|
|
7
7
|
settingsDefaults
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-563fnad9.js";
|
|
9
9
|
import {
|
|
10
10
|
DevicesDoc,
|
|
11
11
|
RevocationsDoc,
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
MAX_ATTACHMENT_NAME_LENGTH,
|
|
39
39
|
MAX_PENDING_ATTACHMENTS,
|
|
40
40
|
MAX_PENDING_ATTACHMENT_BYTES,
|
|
41
|
+
MAX_TRANSCRIPT_PAGE,
|
|
41
42
|
PROTOCOL,
|
|
42
43
|
RTC_DATA_CHANNEL_LABEL,
|
|
43
44
|
RTC_DEFAULT_STUN,
|
|
@@ -56,7 +57,7 @@ import {
|
|
|
56
57
|
rtcCandidateType,
|
|
57
58
|
sdpCandidates,
|
|
58
59
|
withRtcCandidates
|
|
59
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-kmzzjv53.js";
|
|
60
61
|
import {
|
|
61
62
|
ENDPOINT_SET_SCHEMA_VERSION,
|
|
62
63
|
MAX_HOST_ENDPOINT_URL_LENGTH,
|
|
@@ -79,7 +80,7 @@ import {
|
|
|
79
80
|
import {
|
|
80
81
|
packagedVersion,
|
|
81
82
|
webRoot
|
|
82
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-s0h7c7da.js";
|
|
83
84
|
import {
|
|
84
85
|
__require
|
|
85
86
|
} from "./chunk-df32avw6.js";
|
|
@@ -178,8 +179,10 @@ var QuestionWait = defineTask({
|
|
|
178
179
|
resolve(initial);
|
|
179
180
|
return;
|
|
180
181
|
}
|
|
181
|
-
watch.start(async (
|
|
182
|
-
|
|
182
|
+
watch.start(async (call) => {
|
|
183
|
+
if (call.kind !== "value")
|
|
184
|
+
return;
|
|
185
|
+
const found = resolutionOf(call.value, task.input.requestId);
|
|
183
186
|
if (found !== undefined)
|
|
184
187
|
resolve(found);
|
|
185
188
|
});
|
|
@@ -3529,24 +3532,29 @@ async function attachPushSender(options) {
|
|
|
3529
3532
|
}
|
|
3530
3533
|
};
|
|
3531
3534
|
const unsubscribeConversations = conversations.subscribe(() => update());
|
|
3532
|
-
const
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
settle
|
|
3546
|
-
|
|
3535
|
+
const commits = harness.observeCommits({
|
|
3536
|
+
advance: (publication) => {
|
|
3537
|
+
for (const change of publication.changes) {
|
|
3538
|
+
if (change.type !== "document" || change.kind !== "change" || change.record.kind !== TitleDoc.definition.kind)
|
|
3539
|
+
continue;
|
|
3540
|
+
const id = change.conversationId;
|
|
3541
|
+
if (id === undefined)
|
|
3542
|
+
continue;
|
|
3543
|
+
const title = change.value.title;
|
|
3544
|
+
if (typeof title !== "string" || title === "")
|
|
3545
|
+
continue;
|
|
3546
|
+
const waiters = titleWaiters.get(id);
|
|
3547
|
+
titleWaiters.delete(id);
|
|
3548
|
+
for (const settle of waiters ?? [])
|
|
3549
|
+
settle(title);
|
|
3550
|
+
}
|
|
3551
|
+
},
|
|
3552
|
+
end: () => {}
|
|
3547
3553
|
});
|
|
3548
|
-
indexWatch?.start(async (
|
|
3549
|
-
|
|
3554
|
+
indexWatch?.start(async (call) => {
|
|
3555
|
+
if (call.kind !== "value")
|
|
3556
|
+
return;
|
|
3557
|
+
index = call.value;
|
|
3550
3558
|
update();
|
|
3551
3559
|
});
|
|
3552
3560
|
update();
|
|
@@ -3555,7 +3563,7 @@ async function attachPushSender(options) {
|
|
|
3555
3563
|
async close() {
|
|
3556
3564
|
disposed = true;
|
|
3557
3565
|
unsubscribeConversations();
|
|
3558
|
-
|
|
3566
|
+
commits.detach();
|
|
3559
3567
|
await indexWatch?.stop();
|
|
3560
3568
|
for (const item of pending)
|
|
3561
3569
|
drop(item);
|
|
@@ -4271,12 +4279,16 @@ class ConversationList {
|
|
|
4271
4279
|
#list = [];
|
|
4272
4280
|
#unsubscribe = () => {};
|
|
4273
4281
|
#notifying = false;
|
|
4282
|
+
#harness;
|
|
4283
|
+
#live = new Map;
|
|
4284
|
+
#disposed = false;
|
|
4274
4285
|
constructor(docs) {
|
|
4275
4286
|
this.#questionTokens = (docs ?? []).filter((doc) => doc.presentation === "pinomad.question").map((doc) => doc.token);
|
|
4276
4287
|
this.#questionKinds = new Set(this.#questionTokens.map((token) => token.definition.kind));
|
|
4277
4288
|
}
|
|
4278
4289
|
static async open(harness, docs) {
|
|
4279
4290
|
const list = new ConversationList(docs);
|
|
4291
|
+
list.#harness = harness;
|
|
4280
4292
|
const summaries = [];
|
|
4281
4293
|
let cursor;
|
|
4282
4294
|
const records = [];
|
|
@@ -4295,10 +4307,13 @@ class ConversationList {
|
|
|
4295
4307
|
summaries.push(list.#summaryOf(record));
|
|
4296
4308
|
}
|
|
4297
4309
|
list.#list = summaries;
|
|
4298
|
-
|
|
4310
|
+
const observation = harness.observeCommits({ advance: (publication) => list.#observe(publication), end: () => {} });
|
|
4311
|
+
list.#unsubscribe = () => observation.detach();
|
|
4299
4312
|
const touched = new Set;
|
|
4300
4313
|
list.#reindex(await harness.snapshot(IndexDoc, context3), touched);
|
|
4301
4314
|
list.#refreshSummaries(touched);
|
|
4315
|
+
for (const [id, facts] of list.#facts)
|
|
4316
|
+
list.#followLive(id, facts.running === true);
|
|
4302
4317
|
return list;
|
|
4303
4318
|
}
|
|
4304
4319
|
async#load(harness, record) {
|
|
@@ -4354,22 +4369,23 @@ class ConversationList {
|
|
|
4354
4369
|
facts.calls = entry.kind === "pi.assistant" ? callsOf(message) : undefined;
|
|
4355
4370
|
} else if (change.type === "document") {
|
|
4356
4371
|
const id = change.conversationId;
|
|
4372
|
+
const value = change.kind === "change" ? change.value : null;
|
|
4357
4373
|
if (id === undefined) {
|
|
4358
4374
|
if (change.record.kind === IndexDoc.definition.kind)
|
|
4359
|
-
this.#reindex(
|
|
4375
|
+
this.#reindex(value, touched);
|
|
4360
4376
|
continue;
|
|
4361
4377
|
}
|
|
4362
4378
|
const facts = this.#fact(id);
|
|
4363
4379
|
if (change.record.kind === "pi.live") {
|
|
4364
|
-
const live =
|
|
4380
|
+
const live = value;
|
|
4365
4381
|
const wasRunning = facts.running === true;
|
|
4366
4382
|
facts.running = live?.run !== undefined;
|
|
4367
4383
|
facts.tools = live?.tools;
|
|
4368
4384
|
touched.add(id);
|
|
4385
|
+
this.#followLive(id, facts.running);
|
|
4369
4386
|
if (wasRunning && !facts.running && this.#records.get(id)?.owner === undefined)
|
|
4370
4387
|
ended.add(id);
|
|
4371
4388
|
} else if (this.#questionKinds.has(change.record.kind)) {
|
|
4372
|
-
const value = change.value;
|
|
4373
4389
|
const pending = Value2.Check(QuestionSchema, value) && value.requests.some((request) => request.resolution === undefined);
|
|
4374
4390
|
const next = new Set(facts.pending);
|
|
4375
4391
|
if (pending)
|
|
@@ -4379,16 +4395,16 @@ class ConversationList {
|
|
|
4379
4395
|
facts.pending = next;
|
|
4380
4396
|
touched.add(id);
|
|
4381
4397
|
} else if (change.record.kind === RoleDoc.definition.kind) {
|
|
4382
|
-
facts.agent = roleNameOf(
|
|
4398
|
+
facts.agent = roleNameOf(value);
|
|
4383
4399
|
touched.add(id);
|
|
4384
4400
|
} else if (change.record.kind === SubagentDoc.definition.kind) {
|
|
4385
|
-
const
|
|
4386
|
-
facts.label = typeof
|
|
4387
|
-
facts.role = typeof
|
|
4388
|
-
facts.model = modelRefOf(
|
|
4401
|
+
const subagent = value;
|
|
4402
|
+
facts.label = typeof subagent?.label === "string" && subagent.label !== "" ? subagent.label : undefined;
|
|
4403
|
+
facts.role = typeof subagent?.role === "string" && subagent.role !== "" ? subagent.role : undefined;
|
|
4404
|
+
facts.model = modelRefOf(subagent?.model);
|
|
4389
4405
|
touched.add(id);
|
|
4390
4406
|
} else if (change.record.kind === TitleDoc.definition.kind) {
|
|
4391
|
-
const named =
|
|
4407
|
+
const named = value?.title;
|
|
4392
4408
|
facts.named = typeof named === "string" && named !== "" ? named : undefined;
|
|
4393
4409
|
touched.add(id);
|
|
4394
4410
|
}
|
|
@@ -4463,9 +4479,51 @@ class ConversationList {
|
|
|
4463
4479
|
listener(this.#list);
|
|
4464
4480
|
});
|
|
4465
4481
|
}
|
|
4482
|
+
#followLive(id, running) {
|
|
4483
|
+
if (!running || this.#disposed) {
|
|
4484
|
+
const watch = this.#live.get(id);
|
|
4485
|
+
this.#live.delete(id);
|
|
4486
|
+
watch?.stop();
|
|
4487
|
+
return;
|
|
4488
|
+
}
|
|
4489
|
+
if (this.#live.has(id))
|
|
4490
|
+
return;
|
|
4491
|
+
this.#live.set(id, undefined);
|
|
4492
|
+
setImmediate(() => {
|
|
4493
|
+
this.#harness.watchDoc(LiveDoc, id, context3).then(async (watch) => {
|
|
4494
|
+
if (watch === undefined)
|
|
4495
|
+
return;
|
|
4496
|
+
if (this.#live.get(id) !== undefined || !this.#live.has(id)) {
|
|
4497
|
+
await watch.stop();
|
|
4498
|
+
return;
|
|
4499
|
+
}
|
|
4500
|
+
this.#live.set(id, watch);
|
|
4501
|
+
const apply = (live) => {
|
|
4502
|
+
const facts = this.#fact(id);
|
|
4503
|
+
if (live.run === undefined)
|
|
4504
|
+
return;
|
|
4505
|
+
facts.tools = live.tools;
|
|
4506
|
+
this.#refreshSummaries(new Set([id]));
|
|
4507
|
+
};
|
|
4508
|
+
apply(watch.value);
|
|
4509
|
+
watch.start(async (call) => {
|
|
4510
|
+
if (call.kind === "value")
|
|
4511
|
+
apply(call.value);
|
|
4512
|
+
});
|
|
4513
|
+
}, (error) => {
|
|
4514
|
+
if (this.#live.get(id) === undefined)
|
|
4515
|
+
this.#live.delete(id);
|
|
4516
|
+
console.error(`conversation ${id}: could not follow pi.live: ${error instanceof Error ? error.message : String(error)}`);
|
|
4517
|
+
});
|
|
4518
|
+
});
|
|
4519
|
+
}
|
|
4466
4520
|
dispose() {
|
|
4521
|
+
this.#disposed = true;
|
|
4467
4522
|
this.#unsubscribe();
|
|
4468
4523
|
this.#listeners.clear();
|
|
4524
|
+
for (const watch of this.#live.values())
|
|
4525
|
+
watch?.stop();
|
|
4526
|
+
this.#live.clear();
|
|
4469
4527
|
}
|
|
4470
4528
|
}
|
|
4471
4529
|
function roleNameOf(value) {
|
|
@@ -4534,6 +4592,38 @@ function titleOf(entry) {
|
|
|
4534
4592
|
const title = stripUserBlocks(message.content).text.replace(/\s+/g, " ").trim();
|
|
4535
4593
|
return title === "" ? {} : { title };
|
|
4536
4594
|
}
|
|
4595
|
+
var WHOLE_TRANSCRIPT = { min: Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER };
|
|
4596
|
+
var TURN_STARTS = new Set(["pi.user", "pi.compaction", "pi.reset"]);
|
|
4597
|
+
async function turnPage(conversation, before, limit) {
|
|
4598
|
+
const want = Math.min(limit, MAX_TRANSCRIPT_PAGE);
|
|
4599
|
+
const done = (taken2) => taken2.length >= MAX_TRANSCRIPT_PAGE || taken2.length >= want && TURN_STARTS.has(taken2.at(-1).kind);
|
|
4600
|
+
const query = { order: "descending", ...before === undefined ? {} : { maxEntryId: before } };
|
|
4601
|
+
const taken = [];
|
|
4602
|
+
let cursor;
|
|
4603
|
+
for (;; ) {
|
|
4604
|
+
const page = await conversation.entries(query, Math.max(want + 1 - taken.length, 64), cursor, context3);
|
|
4605
|
+
for (const entry of page.items) {
|
|
4606
|
+
if (done(taken))
|
|
4607
|
+
return { entries: taken.reverse(), before: entry.id };
|
|
4608
|
+
taken.push(entry);
|
|
4609
|
+
}
|
|
4610
|
+
if (page.next === undefined)
|
|
4611
|
+
return { entries: taken.reverse() };
|
|
4612
|
+
cursor = page.next;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
async function viewWindow(conversation, window) {
|
|
4616
|
+
if (window === undefined)
|
|
4617
|
+
return WHOLE_TRANSCRIPT;
|
|
4618
|
+
const from = window.from ?? await startOf(conversation, window.limit);
|
|
4619
|
+
return from === undefined ? WHOLE_TRANSCRIPT : { ...WHOLE_TRANSCRIPT, from };
|
|
4620
|
+
}
|
|
4621
|
+
async function startOf(conversation, limit) {
|
|
4622
|
+
const page = await turnPage(conversation, undefined, limit);
|
|
4623
|
+
return page.before === undefined ? undefined : page.entries[0].id;
|
|
4624
|
+
}
|
|
4625
|
+
var shownOps = (call) => isGone(call) ? [["r", null]] : call.ops;
|
|
4626
|
+
var isGone = (call) => call.retired && !call.ops.some((op) => op[0] === "r");
|
|
4537
4627
|
async function historyFacts(harness, id) {
|
|
4538
4628
|
const conversation = await harness.conversation(id, context3);
|
|
4539
4629
|
let first;
|
|
@@ -4745,15 +4835,19 @@ class GatewayClient {
|
|
|
4745
4835
|
}
|
|
4746
4836
|
async#receive(frame) {
|
|
4747
4837
|
if (frame.type === "subscribe")
|
|
4748
|
-
await this.#subscribe(frame.stream, frame.images === "ref", frame.since);
|
|
4838
|
+
await this.#subscribe(frame.stream, frame.images === "ref", frame.since, frame.window);
|
|
4749
4839
|
else if (frame.type === "unsubscribe")
|
|
4750
4840
|
await this.#unsubscribe(frame.stream);
|
|
4751
4841
|
else
|
|
4752
4842
|
await this.#answer(frame.id, frame.method, frame.args);
|
|
4753
4843
|
}
|
|
4754
|
-
async#subscribe(stream, imageRefs, since) {
|
|
4844
|
+
async#subscribe(stream, imageRefs, since, window) {
|
|
4755
4845
|
const previous = this.#subscriptions.get(stream);
|
|
4756
|
-
const state =
|
|
4846
|
+
const state = {
|
|
4847
|
+
...imageRefs && stream.startsWith("conversation:") ? { images: new ImageRefs } : {},
|
|
4848
|
+
...since === undefined ? {} : { since },
|
|
4849
|
+
...window === undefined ? {} : { window }
|
|
4850
|
+
};
|
|
4757
4851
|
this.#subscriptions.set(stream, state);
|
|
4758
4852
|
const current = () => !this.#disposed && this.#subscriptions.get(stream) === state;
|
|
4759
4853
|
const send = (frame) => current() ? this.send(frame) : Promise.resolve();
|
|
@@ -4820,7 +4914,7 @@ class GatewayClient {
|
|
|
4820
4914
|
return this.#openDoc(stream, stream.slice("doc:".length, at), Number(stream.slice(at + 1)), send);
|
|
4821
4915
|
}
|
|
4822
4916
|
const conversation = await this.#conversation(Number(stream.slice("conversation:".length)));
|
|
4823
|
-
return this.#forward(stream, await conversation.watch(context3), send, state);
|
|
4917
|
+
return this.#forward(stream, await conversation.watch(context3, await viewWindow(conversation, state?.window)), send, state);
|
|
4824
4918
|
}
|
|
4825
4919
|
#hostValue(stream) {
|
|
4826
4920
|
return Object.hasOwn(this.#hostValues, stream) ? this.#hostValues[stream] : undefined;
|
|
@@ -4838,13 +4932,17 @@ class GatewayClient {
|
|
|
4838
4932
|
});
|
|
4839
4933
|
let inner;
|
|
4840
4934
|
let stopped = false;
|
|
4841
|
-
const
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4935
|
+
const observation = harness.observeCommits({
|
|
4936
|
+
advance: (publication) => {
|
|
4937
|
+
const matches = publication.changes.some((change) => (change.type === "document" || change.type === "document.copy") && change.record.kind === kind && change.conversationId === id);
|
|
4938
|
+
if (!matches)
|
|
4939
|
+
return;
|
|
4940
|
+
unsubscribe();
|
|
4941
|
+
setImmediate(() => signalCreation());
|
|
4942
|
+
},
|
|
4943
|
+
end: () => {}
|
|
4847
4944
|
});
|
|
4945
|
+
const unsubscribe = () => observation.detach();
|
|
4848
4946
|
try {
|
|
4849
4947
|
const existing = await harness.watchDoc(token, id, context3);
|
|
4850
4948
|
if (existing !== undefined) {
|
|
@@ -4885,16 +4983,19 @@ class GatewayClient {
|
|
|
4885
4983
|
async#forward(stream, watch, send, state) {
|
|
4886
4984
|
if (state?.images === undefined) {
|
|
4887
4985
|
await send({ type: "snapshot", stream, value: watch.value });
|
|
4888
|
-
watch.start((
|
|
4986
|
+
watch.start((call) => call.kind === "value" ? send({ type: "ops", stream, ops: shownOps(call) }) : Promise.resolve());
|
|
4889
4987
|
return watch;
|
|
4890
4988
|
}
|
|
4891
4989
|
const images = state.images;
|
|
4892
4990
|
let before = watch.value;
|
|
4893
4991
|
state.view = before;
|
|
4894
4992
|
await send({ type: "snapshot", stream, value: await images.value(before) });
|
|
4895
|
-
watch.start(async (
|
|
4993
|
+
watch.start(async (call) => {
|
|
4994
|
+
if (call.kind !== "value")
|
|
4995
|
+
return;
|
|
4996
|
+
const ops = shownOps(call);
|
|
4896
4997
|
const sent = await images.ops(ops, before);
|
|
4897
|
-
before = value;
|
|
4998
|
+
before = isGone(call) ? null : call.value;
|
|
4898
4999
|
state.view = before;
|
|
4899
5000
|
return send({ type: "ops", stream, ops: sent });
|
|
4900
5001
|
});
|
|
@@ -4904,7 +5005,7 @@ class GatewayClient {
|
|
|
4904
5005
|
for (const state of this.#subscriptions.values()) {
|
|
4905
5006
|
if (state.images === undefined || state.view === undefined)
|
|
4906
5007
|
continue;
|
|
4907
|
-
const image = state.images.image(state.view, ref);
|
|
5008
|
+
const image = state.images.image(state.view, ref) ?? (state.earlier === undefined ? undefined : state.images.image({ entries: state.earlier }, ref));
|
|
4908
5009
|
if (image !== undefined)
|
|
4909
5010
|
return image;
|
|
4910
5011
|
}
|
|
@@ -5168,6 +5269,26 @@ class GatewayClient {
|
|
|
5168
5269
|
const input = args;
|
|
5169
5270
|
return listSkills(this.#options.harness, this.#skills, input.scope, context3);
|
|
5170
5271
|
}
|
|
5272
|
+
case "earlierEntries": {
|
|
5273
|
+
const { conversationId, before, limit } = args;
|
|
5274
|
+
const stream = `conversation:${conversationId}`;
|
|
5275
|
+
const state = this.#subscriptions.get(stream);
|
|
5276
|
+
if (state === undefined)
|
|
5277
|
+
throw new Error(`Not subscribed to conversation ${conversationId}`);
|
|
5278
|
+
const replaced = () => this.#subscriptions.get(stream) !== state;
|
|
5279
|
+
const resubscribed = () => new Error(`Conversation ${conversationId} was resubscribed while its page loaded`);
|
|
5280
|
+
const page = await turnPage(await this.#conversation(conversationId), before, limit);
|
|
5281
|
+
if (replaced())
|
|
5282
|
+
throw resubscribed();
|
|
5283
|
+
if (state.images === undefined)
|
|
5284
|
+
return page;
|
|
5285
|
+
const raw = page.entries;
|
|
5286
|
+
const { entries } = await state.images.value({ entries: raw });
|
|
5287
|
+
if (replaced())
|
|
5288
|
+
throw resubscribed();
|
|
5289
|
+
state.earlier = [...state.earlier ?? [], ...raw];
|
|
5290
|
+
return { ...page, entries };
|
|
5291
|
+
}
|
|
5171
5292
|
case "image": {
|
|
5172
5293
|
const input = args;
|
|
5173
5294
|
const image = this.#shownImage(input.ref);
|
|
@@ -5229,6 +5350,37 @@ class GatewayClient {
|
|
|
5229
5350
|
return { outcome: "steered" };
|
|
5230
5351
|
}, context3);
|
|
5231
5352
|
}
|
|
5353
|
+
case "reorderQueued": {
|
|
5354
|
+
const { conversationId, submissionId, before } = args;
|
|
5355
|
+
return await this.#options.harness.commit(async (tx) => {
|
|
5356
|
+
const queuedState = async (id) => {
|
|
5357
|
+
const record = await tx.submission(id);
|
|
5358
|
+
if (record === undefined)
|
|
5359
|
+
throw new Error(`Submission ${id} does not exist`);
|
|
5360
|
+
assertQueuedInput(record, conversationId);
|
|
5361
|
+
if (record.entry !== undefined)
|
|
5362
|
+
return "sent";
|
|
5363
|
+
return record.status === "queued" ? "queued" : "unavailable";
|
|
5364
|
+
};
|
|
5365
|
+
const moved = await queuedState(submissionId);
|
|
5366
|
+
if (moved !== "queued")
|
|
5367
|
+
return { outcome: moved };
|
|
5368
|
+
if (before !== undefined && await queuedState(before) !== "queued") {
|
|
5369
|
+
return { outcome: "unavailable" };
|
|
5370
|
+
}
|
|
5371
|
+
if (before === submissionId)
|
|
5372
|
+
return { outcome: "moved" };
|
|
5373
|
+
const items = (await tx.doc(InboxDoc, conversationId)).items;
|
|
5374
|
+
const from = items.findIndex((candidate) => candidate.id === submissionId);
|
|
5375
|
+
if (from < 0 || before !== undefined && !items.some((candidate) => candidate.id === before)) {
|
|
5376
|
+
return { outcome: "unavailable" };
|
|
5377
|
+
}
|
|
5378
|
+
const [item] = items.splice(from, 1);
|
|
5379
|
+
const to = before === undefined ? items.findLastIndex((candidate) => candidate.mode !== "write") + 1 : items.findIndex((candidate) => candidate.id === before);
|
|
5380
|
+
items.splice(to, 0, item);
|
|
5381
|
+
return { outcome: "moved" };
|
|
5382
|
+
}, context3);
|
|
5383
|
+
}
|
|
5232
5384
|
case "renameConversation": {
|
|
5233
5385
|
const { title } = args;
|
|
5234
5386
|
const trimmed = title.trim();
|
|
@@ -6887,6 +7039,45 @@ async function openModelAuth(runtime, options) {
|
|
|
6887
7039
|
tail = next.catch(() => {});
|
|
6888
7040
|
return next;
|
|
6889
7041
|
};
|
|
7042
|
+
const opened = await readModelsFile(options.modelsPath);
|
|
7043
|
+
Promise.all([...custom].flatMap(([id, endpoint]) => {
|
|
7044
|
+
const entries = opened.providers[id]?.models;
|
|
7045
|
+
if (!Array.isArray(entries) || !entries.some(lacksLimits))
|
|
7046
|
+
return [];
|
|
7047
|
+
return [
|
|
7048
|
+
(async () => {
|
|
7049
|
+
const key = (await runtime.getAuth(id))?.auth.apiKey;
|
|
7050
|
+
const listed = await fetchEndpointModels(endpoint.api, endpoint.baseUrl, key).catch(() => []);
|
|
7051
|
+
return { id, endpoint, listed: new Map(listed.map((model) => [model.id, model])) };
|
|
7052
|
+
})()
|
|
7053
|
+
];
|
|
7054
|
+
})).then((answers) => serial(async () => {
|
|
7055
|
+
if (closed)
|
|
7056
|
+
return;
|
|
7057
|
+
const filled = new Set;
|
|
7058
|
+
const fill = (target) => {
|
|
7059
|
+
for (const { id, endpoint, listed } of answers) {
|
|
7060
|
+
const entry = target.providers[id];
|
|
7061
|
+
if (entry?.api !== endpoint.api || entry.baseUrl !== endpoint.baseUrl || !Array.isArray(entry.models))
|
|
7062
|
+
continue;
|
|
7063
|
+
for (const model of entry.models) {
|
|
7064
|
+
const limits = listed.get(model.id);
|
|
7065
|
+
for (const field of LIMITS) {
|
|
7066
|
+
if (field in model || limits?.[field] === undefined)
|
|
7067
|
+
continue;
|
|
7068
|
+
model[field] = limits[field];
|
|
7069
|
+
filled.add(id);
|
|
7070
|
+
}
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7073
|
+
};
|
|
7074
|
+
fill(await readModelsFile(options.modelsPath));
|
|
7075
|
+
if (filled.size === 0)
|
|
7076
|
+
return;
|
|
7077
|
+
await updateModelsFile(fill);
|
|
7078
|
+
await runtime.refresh({ providers: [...filled], allowNetwork: false });
|
|
7079
|
+
await republish();
|
|
7080
|
+
}));
|
|
6890
7081
|
return {
|
|
6891
7082
|
models,
|
|
6892
7083
|
auth,
|
|
@@ -7092,6 +7283,8 @@ async function fetchEndpointModels(api, baseUrl, key) {
|
|
|
7092
7283
|
throw new Error(`${url.host} listed no models`);
|
|
7093
7284
|
return models;
|
|
7094
7285
|
}
|
|
7286
|
+
var LIMITS = ["contextWindow", "maxTokens"];
|
|
7287
|
+
var lacksLimits = (model) => typeof model === "object" && model !== null && LIMITS.some((field) => !(field in model));
|
|
7095
7288
|
var positive = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
7096
7289
|
function endpointModel(id, reported) {
|
|
7097
7290
|
return {
|
|
@@ -7252,7 +7445,7 @@ async function main(argv) {
|
|
|
7252
7445
|
process.on("SIGINT", stop);
|
|
7253
7446
|
process.on("SIGTERM", stop);
|
|
7254
7447
|
host.closed.then((end) => {
|
|
7255
|
-
if (end.
|
|
7448
|
+
if (end.kind !== "failed" || stopping)
|
|
7256
7449
|
return;
|
|
7257
7450
|
stopping = true;
|
|
7258
7451
|
stopLogRotation();
|
|
@@ -8,17 +8,17 @@ import {
|
|
|
8
8
|
reachabilityLine,
|
|
9
9
|
serviceManager,
|
|
10
10
|
versionLine
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import"./chunk-
|
|
11
|
+
} from "./chunk-wd7aracm.js";
|
|
12
|
+
import"./chunk-4fferbxw.js";
|
|
13
13
|
import"./chunk-kzbzacz9.js";
|
|
14
|
-
import"./chunk-
|
|
14
|
+
import"./chunk-kmzzjv53.js";
|
|
15
15
|
import"./chunk-pqe7q1s7.js";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_DATA_DIR
|
|
18
18
|
} from "./chunk-ngf1zatm.js";
|
|
19
19
|
import {
|
|
20
20
|
commandHint
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-s0h7c7da.js";
|
|
22
22
|
import"./chunk-df32avw6.js";
|
|
23
23
|
|
|
24
24
|
// apps/host/src/cli/status.ts
|