@lamplitisles/codex-for-love 0.4.0 → 0.4.1
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/package.json +1 -1
- package/vendor/IMPORTS.md +1 -1
- package/vendor/build/_app/immutable/assets/0.BI9m5aW9.css +2 -0
- package/vendor/build/_app/immutable/assets/2.GU_203nr.css +1 -0
- package/vendor/build/_app/immutable/chunks/Bg1Ry2sd.js +1 -0
- package/vendor/build/_app/immutable/chunks/CTZw3jzS.js +3 -0
- package/vendor/build/_app/immutable/chunks/CtNIUOtb.js +1147 -0
- package/vendor/build/_app/immutable/chunks/uBIymjUX.js +1 -0
- package/vendor/build/_app/immutable/entry/app.CAV4mc4Y.js +2 -0
- package/vendor/build/_app/immutable/entry/start.C7zzoZ2c.js +1 -0
- package/vendor/build/_app/immutable/nodes/0.sNCrAP8k.js +1 -0
- package/vendor/build/_app/immutable/nodes/{1.B1qFIsWm.js → 1.CcVh3vuf.js} +1 -1
- package/vendor/build/_app/immutable/nodes/2.D1r5MxMF.js +327 -0
- package/vendor/build/_app/version.json +1 -1
- package/vendor/build/index.html +10 -9
- package/vendor/config.example.toml +4 -0
- package/vendor/runtime/cli.mjs +271 -9
- package/vendor/runtime/companion-mcp.mjs +2 -1
- package/vendor/build/_app/immutable/assets/0._f6eIGbJ.css +0 -2
- package/vendor/build/_app/immutable/assets/2.D_B1Of5x.css +0 -1
- package/vendor/build/_app/immutable/chunks/DdacV1pJ.js +0 -1
- package/vendor/build/_app/immutable/chunks/DtqGwW3l.js +0 -3
- package/vendor/build/_app/immutable/entry/app.ROL0GFnN.js +0 -2
- package/vendor/build/_app/immutable/entry/start.D1dr4Kbn.js +0 -1
- package/vendor/build/_app/immutable/nodes/0.-C44RqM4.js +0 -1
- package/vendor/build/_app/immutable/nodes/2.TXBnv1oE.js +0 -326
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"
|
|
1
|
+
{"version":"1789562160506"}
|
package/vendor/build/index.html
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en" data-theme="sticker-messenger">
|
|
3
|
-
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><script>(function(){try{var appearance=localStorage.getItem('lamplitisles.companion.appearance');var language=localStorage.getItem('lamplitisles.companion.language');var systemDark=matchMedia('(prefers-color-scheme: dark)').matches;var dark=appearance==='dark'||(appearance!=='light'&&systemDark);document.documentElement.dataset.theme=dark?'night-voyage':'sticker-messenger';document.documentElement.lang=language==='zh'?'zh-Hans':'en'}catch(_){var systemDark=matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.dataset.theme=systemDark?'night-voyage':'sticker-messenger'}})();</script><link href="/_app/immutable/entry/start.
|
|
4
|
-
<link href="/_app/immutable/chunks/
|
|
5
|
-
<link href="/_app/immutable/chunks/
|
|
6
|
-
<link href="/_app/immutable/entry/app.
|
|
3
|
+
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><script>(function(){try{var appearance=localStorage.getItem('lamplitisles.companion.appearance');var language=localStorage.getItem('lamplitisles.companion.language');var systemDark=matchMedia('(prefers-color-scheme: dark)').matches;var dark=appearance==='dark'||(appearance!=='light'&&systemDark);document.documentElement.dataset.theme=dark?'night-voyage':'sticker-messenger';document.documentElement.lang=language==='zh'?'zh-Hans':'en'}catch(_){var systemDark=matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.dataset.theme=systemDark?'night-voyage':'sticker-messenger'}})();</script><link href="/_app/immutable/entry/start.C7zzoZ2c.js" rel="modulepreload">
|
|
4
|
+
<link href="/_app/immutable/chunks/Bg1Ry2sd.js" rel="modulepreload">
|
|
5
|
+
<link href="/_app/immutable/chunks/CTZw3jzS.js" rel="modulepreload">
|
|
6
|
+
<link href="/_app/immutable/entry/app.CAV4mc4Y.js" rel="modulepreload">
|
|
7
|
+
<link href="/_app/immutable/chunks/uBIymjUX.js" rel="modulepreload">
|
|
7
8
|
<link href="/_app/immutable/chunks/xihTtKlq.js" rel="modulepreload">
|
|
8
|
-
<link href="/_app/immutable/nodes/0
|
|
9
|
+
<link href="/_app/immutable/nodes/0.sNCrAP8k.js" rel="modulepreload">
|
|
9
10
|
|
|
10
|
-
<link href="/_app/immutable/assets/0.
|
|
11
|
+
<link href="/_app/immutable/assets/0.BI9m5aW9.css" rel="stylesheet"></head>
|
|
11
12
|
<body data-sveltekit-preload-data="hover"><div style="display: contents">
|
|
12
13
|
<script>
|
|
13
14
|
{
|
|
14
|
-
|
|
15
|
+
__sveltekit_2j1r7b = {
|
|
15
16
|
base: ""
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const element = document.currentScript.parentElement;
|
|
19
20
|
|
|
20
21
|
Promise.all([
|
|
21
|
-
import("/_app/immutable/entry/start.
|
|
22
|
-
import("/_app/immutable/entry/app.
|
|
22
|
+
import("/_app/immutable/entry/start.C7zzoZ2c.js"),
|
|
23
|
+
import("/_app/immutable/entry/app.CAV4mc4Y.js")
|
|
23
24
|
]).then(([kit, app]) => {
|
|
24
25
|
kit.start(app, element);
|
|
25
26
|
});
|
|
@@ -21,6 +21,10 @@ model = "gpt-5.6-luna"
|
|
|
21
21
|
# local_compaction = true
|
|
22
22
|
# home = "/path/to/a/Codex-home" # omit to use the existing Codex login
|
|
23
23
|
|
|
24
|
+
# Optional browser pet. Disabled by default; restart Partner after changing it.
|
|
25
|
+
#[pet]
|
|
26
|
+
#enabled = true
|
|
27
|
+
|
|
24
28
|
# Optional local Keet-for-Agent gateway. Both fields and a stdin-only `keet`
|
|
25
29
|
# credential enable it; omit either field to keep ordinary local conversation.
|
|
26
30
|
#[keet]
|
package/vendor/runtime/cli.mjs
CHANGED
|
@@ -6217,7 +6217,8 @@ const schema = object({
|
|
|
6217
6217
|
keet: object({
|
|
6218
6218
|
endpoint: string().min(1).optional(),
|
|
6219
6219
|
media_root: string().min(1).optional()
|
|
6220
|
-
}).strict().optional()
|
|
6220
|
+
}).strict().optional(),
|
|
6221
|
+
pet: object({ enabled: boolean().default(false) }).strict().default({ enabled: false })
|
|
6221
6222
|
}).strict();
|
|
6222
6223
|
async function loadConfig(path) {
|
|
6223
6224
|
const config = schema.parse(parse$2(await readFile(path, "utf8")));
|
|
@@ -65339,6 +65340,217 @@ function processError(event, error, details = {}) {
|
|
|
65339
65340
|
...event === "event.failed" ? {} : { error: redactError(message) }
|
|
65340
65341
|
});
|
|
65341
65342
|
}
|
|
65343
|
+
//#endregion
|
|
65344
|
+
//#region apps/partner/runtime/pet.ts
|
|
65345
|
+
/** The deliberately small, browser-safe representation of companion activity. */
|
|
65346
|
+
const PET_ACTIVITIES = [
|
|
65347
|
+
"idle",
|
|
65348
|
+
"thinking",
|
|
65349
|
+
"read",
|
|
65350
|
+
"work",
|
|
65351
|
+
"replying",
|
|
65352
|
+
"success",
|
|
65353
|
+
"concern"
|
|
65354
|
+
];
|
|
65355
|
+
/**
|
|
65356
|
+
* Converts app-server lifecycle metadata into a finite presentation state.
|
|
65357
|
+
* Never retain item text, arguments, results, paths, commands, or errors here.
|
|
65358
|
+
*/
|
|
65359
|
+
var PetActivityProjection = class {
|
|
65360
|
+
#activity = "idle";
|
|
65361
|
+
#revision = 0;
|
|
65362
|
+
#turnActive = false;
|
|
65363
|
+
#items = /* @__PURE__ */ new Map();
|
|
65364
|
+
#timer;
|
|
65365
|
+
#changed;
|
|
65366
|
+
#durations;
|
|
65367
|
+
constructor(changed = () => {}, durations = {
|
|
65368
|
+
success: 1200,
|
|
65369
|
+
concern: 2e3
|
|
65370
|
+
}) {
|
|
65371
|
+
this.#changed = changed;
|
|
65372
|
+
this.#durations = durations;
|
|
65373
|
+
}
|
|
65374
|
+
snapshot() {
|
|
65375
|
+
return {
|
|
65376
|
+
activity: this.#activity,
|
|
65377
|
+
revision: this.#revision
|
|
65378
|
+
};
|
|
65379
|
+
}
|
|
65380
|
+
close() {
|
|
65381
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
65382
|
+
}
|
|
65383
|
+
idle() {
|
|
65384
|
+
this.#turnActive = false;
|
|
65385
|
+
this.#items.clear();
|
|
65386
|
+
this.#set("idle");
|
|
65387
|
+
}
|
|
65388
|
+
turnStarted() {
|
|
65389
|
+
this.#turnActive = true;
|
|
65390
|
+
this.#set("thinking");
|
|
65391
|
+
}
|
|
65392
|
+
itemStarted(item) {
|
|
65393
|
+
this.#turnActive = true;
|
|
65394
|
+
const activity = activityForItem(item);
|
|
65395
|
+
const id = typeof item.id === "string" ? item.id : `anonymous:${this.#items.size}`;
|
|
65396
|
+
this.#items.set(id, activity);
|
|
65397
|
+
this.#set(activity);
|
|
65398
|
+
}
|
|
65399
|
+
itemCompleted(item) {
|
|
65400
|
+
const id = typeof item.id === "string" ? item.id : void 0;
|
|
65401
|
+
if (id) this.#items.delete(id);
|
|
65402
|
+
if (failedItem(item)) this.#transient("concern", 2e3);
|
|
65403
|
+
else this.#set(this.#current());
|
|
65404
|
+
}
|
|
65405
|
+
turnCompleted(status) {
|
|
65406
|
+
this.#turnActive = false;
|
|
65407
|
+
this.#items.clear();
|
|
65408
|
+
this.#transient([
|
|
65409
|
+
"failed",
|
|
65410
|
+
"cancelled",
|
|
65411
|
+
"interrupted"
|
|
65412
|
+
].includes(String(status)) ? "concern" : "success", [
|
|
65413
|
+
"failed",
|
|
65414
|
+
"cancelled",
|
|
65415
|
+
"interrupted"
|
|
65416
|
+
].includes(String(status)) ? this.#durations.concern : this.#durations.success);
|
|
65417
|
+
}
|
|
65418
|
+
#current() {
|
|
65419
|
+
return [...this.#items.values()].at(-1) ?? (this.#turnActive ? "thinking" : "idle");
|
|
65420
|
+
}
|
|
65421
|
+
#transient(activity, ms) {
|
|
65422
|
+
this.#set(activity);
|
|
65423
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
65424
|
+
this.#timer = setTimeout(() => {
|
|
65425
|
+
this.#timer = void 0;
|
|
65426
|
+
this.#set(this.#current());
|
|
65427
|
+
}, ms);
|
|
65428
|
+
}
|
|
65429
|
+
#set(activity) {
|
|
65430
|
+
if (this.#timer && !["success", "concern"].includes(activity)) {
|
|
65431
|
+
clearTimeout(this.#timer);
|
|
65432
|
+
this.#timer = void 0;
|
|
65433
|
+
}
|
|
65434
|
+
if (this.#activity !== activity) {
|
|
65435
|
+
this.#activity = activity;
|
|
65436
|
+
this.#revision += 1;
|
|
65437
|
+
this.#changed();
|
|
65438
|
+
}
|
|
65439
|
+
}
|
|
65440
|
+
};
|
|
65441
|
+
function activityForItem(item) {
|
|
65442
|
+
switch (item.type) {
|
|
65443
|
+
case "agentMessage": return "replying";
|
|
65444
|
+
case "webSearch":
|
|
65445
|
+
case "web": return "read";
|
|
65446
|
+
case "commandExecution":
|
|
65447
|
+
case "fileChange":
|
|
65448
|
+
case "imageGeneration": return "work";
|
|
65449
|
+
case "mcpToolCall": return activityForMcp(String(item.server ?? ""), String(item.tool ?? ""));
|
|
65450
|
+
default: return "thinking";
|
|
65451
|
+
}
|
|
65452
|
+
}
|
|
65453
|
+
function activityForMcp(server, tool) {
|
|
65454
|
+
if (server === "companion") {
|
|
65455
|
+
if (tool === "read_relationship_history") return "read";
|
|
65456
|
+
if (tool === "send_voice" || tool === "roll_dice") return tool === "send_voice" ? "replying" : "thinking";
|
|
65457
|
+
return "work";
|
|
65458
|
+
}
|
|
65459
|
+
if (server === "keet") return tool === "keet_send_message" || tool === "send_message" ? "replying" : "read";
|
|
65460
|
+
if (server === "web" || server === "openaiDeveloperDocs") return "read";
|
|
65461
|
+
if ([
|
|
65462
|
+
"project",
|
|
65463
|
+
"flicknote",
|
|
65464
|
+
"guion-email",
|
|
65465
|
+
"og",
|
|
65466
|
+
"skill"
|
|
65467
|
+
].includes(server)) return /(?:create|edit|update|write|send|apply|delete|move|organize)/iu.test(tool) ? server === "guion-email" && /(?:draft|send)/iu.test(tool) ? "replying" : "work" : "read";
|
|
65468
|
+
return "thinking";
|
|
65469
|
+
}
|
|
65470
|
+
function failedItem(item) {
|
|
65471
|
+
return [
|
|
65472
|
+
"failed",
|
|
65473
|
+
"error",
|
|
65474
|
+
"cancelled",
|
|
65475
|
+
"interrupted"
|
|
65476
|
+
].includes(String(item.status));
|
|
65477
|
+
}
|
|
65478
|
+
//#endregion
|
|
65479
|
+
//#region apps/partner/runtime/pet-assets.ts
|
|
65480
|
+
const clip = object({
|
|
65481
|
+
file: string().regex(/^[a-z]+\.webp$/u),
|
|
65482
|
+
frameCount: union([literal(6), literal(8)]),
|
|
65483
|
+
fps: number$1().int().min(1).max(24),
|
|
65484
|
+
loop: boolean()
|
|
65485
|
+
}).strict();
|
|
65486
|
+
const manifestSchema = object({
|
|
65487
|
+
schemaVersion: literal(2),
|
|
65488
|
+
character: literal("shio"),
|
|
65489
|
+
revision: string().min(1).max(80),
|
|
65490
|
+
clips: object(Object.fromEntries(PET_ACTIVITIES.map((a) => [a, clip]))).strict()
|
|
65491
|
+
}).strict();
|
|
65492
|
+
const MAX_SHEET_BYTES = 15e5;
|
|
65493
|
+
async function localPetClip(state, activity) {
|
|
65494
|
+
const root = join(state, "pet-assets");
|
|
65495
|
+
let manifest;
|
|
65496
|
+
try {
|
|
65497
|
+
const parsed = manifestSchema.safeParse(JSON.parse(await readFile(join(root, "manifest.json"), "utf8")));
|
|
65498
|
+
if (!parsed.success) return void 0;
|
|
65499
|
+
manifest = parsed.data;
|
|
65500
|
+
} catch {
|
|
65501
|
+
return;
|
|
65502
|
+
}
|
|
65503
|
+
let selected;
|
|
65504
|
+
for (const candidate of PET_ACTIVITIES) {
|
|
65505
|
+
const data = await readClip(root, manifest.clips[candidate].file, manifest.clips[candidate].frameCount);
|
|
65506
|
+
if (!data) return void 0;
|
|
65507
|
+
if (candidate === activity) selected = data;
|
|
65508
|
+
}
|
|
65509
|
+
return selected ? {
|
|
65510
|
+
data: selected,
|
|
65511
|
+
manifest
|
|
65512
|
+
} : void 0;
|
|
65513
|
+
}
|
|
65514
|
+
function webpDimensions(data) {
|
|
65515
|
+
if (data.length < 20 || Buffer.from(data.subarray(0, 4)).toString() !== "RIFF" || Buffer.from(data.subarray(8, 12)).toString() !== "WEBP") return void 0;
|
|
65516
|
+
for (let offset = 12; offset + 8 <= data.length;) {
|
|
65517
|
+
const type = Buffer.from(data.subarray(offset, offset + 4)).toString();
|
|
65518
|
+
const size = data[offset + 4] | data[offset + 5] << 8 | data[offset + 6] << 16 | data[offset + 7] << 24;
|
|
65519
|
+
const body = offset + 8;
|
|
65520
|
+
if (body + size > data.length) return void 0;
|
|
65521
|
+
if (type === "VP8X" && size >= 10) return {
|
|
65522
|
+
width: 1 + data[body + 4] + (data[body + 5] << 8) + (data[body + 6] << 16),
|
|
65523
|
+
height: 1 + data[body + 7] + (data[body + 8] << 8) + (data[body + 9] << 16)
|
|
65524
|
+
};
|
|
65525
|
+
if (type === "VP8 " && size >= 10 && data[body + 3] === 157 && data[body + 4] === 1 && data[body + 5] === 42) return {
|
|
65526
|
+
width: data[body + 6] | (data[body + 7] & 63) << 8,
|
|
65527
|
+
height: data[body + 8] | (data[body + 9] & 63) << 8
|
|
65528
|
+
};
|
|
65529
|
+
if (type === "VP8L" && size >= 5 && data[body] === 47) return {
|
|
65530
|
+
width: 1 + data[body + 1] + ((data[body + 2] & 63) << 8),
|
|
65531
|
+
height: 1 + (data[body + 2] >> 6) + (data[body + 3] << 2) + ((data[body + 4] & 15) << 10)
|
|
65532
|
+
};
|
|
65533
|
+
offset = body + size + size % 2;
|
|
65534
|
+
}
|
|
65535
|
+
}
|
|
65536
|
+
async function readClip(root, name, frameCount) {
|
|
65537
|
+
if (extname(name) !== ".webp") return void 0;
|
|
65538
|
+
const path = resolve(root, name);
|
|
65539
|
+
if (relative(resolve(root), path).startsWith("..")) return void 0;
|
|
65540
|
+
try {
|
|
65541
|
+
const info = await lstat(path);
|
|
65542
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > MAX_SHEET_BYTES) return void 0;
|
|
65543
|
+
const [actualRoot, actual, data] = await Promise.all([
|
|
65544
|
+
realpath(root),
|
|
65545
|
+
realpath(path),
|
|
65546
|
+
readFile(path)
|
|
65547
|
+
]);
|
|
65548
|
+
const dimensions = webpDimensions(data);
|
|
65549
|
+
return dimensions?.height === 512 && dimensions.width === frameCount * 512 && (actual === actualRoot || actual.startsWith(`${actualRoot}/`)) ? data : void 0;
|
|
65550
|
+
} catch {
|
|
65551
|
+
return;
|
|
65552
|
+
}
|
|
65553
|
+
}
|
|
65342
65554
|
const HISTORY_PAGE_MESSAGES = 50;
|
|
65343
65555
|
/** Match DSH's 50-message history window against CFL's rendered projection. */
|
|
65344
65556
|
function visibleHistoryPage(messages, results, before) {
|
|
@@ -65397,6 +65609,19 @@ function turnTime(value, fallback) {
|
|
|
65397
65609
|
if (number === null) return fallback;
|
|
65398
65610
|
return number > 1e10 ? Math.round(number) : Math.round(number * 1e3);
|
|
65399
65611
|
}
|
|
65612
|
+
function completedTurnTime(value) {
|
|
65613
|
+
const raw = numberOrNull(value);
|
|
65614
|
+
if (raw === null) return void 0;
|
|
65615
|
+
return raw > 1e10 ? Math.round(raw) : Math.round(raw * 1e3);
|
|
65616
|
+
}
|
|
65617
|
+
function inputTimeContext(source, now) {
|
|
65618
|
+
const date = new Date(now);
|
|
65619
|
+
const time = `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
65620
|
+
return {
|
|
65621
|
+
kind: "application",
|
|
65622
|
+
value: `${source === "owner" ? "Current owner input" : "Qualifying Keet input"} received around local ${time}. Trusted delivery metadata; not user-authored text or an instruction.`
|
|
65623
|
+
};
|
|
65624
|
+
}
|
|
65400
65625
|
function textFromUserItem(item) {
|
|
65401
65626
|
if (item.type !== "userMessage" || !Array.isArray(item.content)) return void 0;
|
|
65402
65627
|
return item.content.filter((part) => typeof part === "object" && part !== null && !Array.isArray(part) && part.type === "text").map((part) => part.text).filter((part) => typeof part === "string").join("") || (item.content.length ? "" : void 0);
|
|
@@ -65656,6 +65881,9 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65656
65881
|
let keetFeed;
|
|
65657
65882
|
let keetReconnect;
|
|
65658
65883
|
let keetConnecting = false;
|
|
65884
|
+
const pet = config.pet.enabled ? new PetActivityProjection(() => {
|
|
65885
|
+
if (!closing) notify();
|
|
65886
|
+
}) : void 0;
|
|
65659
65887
|
const notify = () => {
|
|
65660
65888
|
for (const listener of listeners) listener();
|
|
65661
65889
|
};
|
|
@@ -65958,6 +66186,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65958
66186
|
const voiceIds = voiceIdsFromTurn(turn);
|
|
65959
66187
|
let resultError = errorFromTurn(turn);
|
|
65960
66188
|
let resultStatus = status;
|
|
66189
|
+
const completedAt = status === "completed" ? completedTurnTime(turn.completedAt) : void 0;
|
|
65961
66190
|
for (const item of turn.items ?? []) {
|
|
65962
66191
|
if (item.type !== "imageGeneration") continue;
|
|
65963
66192
|
const generatedId = await projectGeneratedImage(resultOperationId(turn.id), sourceIds, item);
|
|
@@ -65974,7 +66203,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65974
66203
|
error: resultError,
|
|
65975
66204
|
status: resultStatus,
|
|
65976
66205
|
generatedIds,
|
|
65977
|
-
voiceIds
|
|
66206
|
+
voiceIds,
|
|
66207
|
+
...completedAt === void 0 ? {} : { completedAt }
|
|
65978
66208
|
};
|
|
65979
66209
|
const fingerprint = JSON.stringify(resultBody);
|
|
65980
66210
|
const previous = presentationFingerprints.get(turn.id);
|
|
@@ -66056,7 +66286,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66056
66286
|
const turn = registerTurn((await appServer.call("turn/start", {
|
|
66057
66287
|
threadId,
|
|
66058
66288
|
input: nativeInput(intent.input, intent.images),
|
|
66059
|
-
clientUserMessageId: intent.transportId
|
|
66289
|
+
clientUserMessageId: intent.transportId,
|
|
66290
|
+
...intent.source !== "none" ? { additionalContext: { "codex-for-love.message-time": inputTimeContext(intent.source, now()) } } : {}
|
|
66060
66291
|
})).turn, intent.ids);
|
|
66061
66292
|
if (!turn) throw new Error("Codex app-server did not return a turn");
|
|
66062
66293
|
intent.turnId = turn.id;
|
|
@@ -66100,7 +66331,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66100
66331
|
threadId,
|
|
66101
66332
|
input: nativeInput(intent.input, intent.images),
|
|
66102
66333
|
clientUserMessageId: intent.transportId,
|
|
66103
|
-
expectedTurnId: expected
|
|
66334
|
+
expectedTurnId: expected,
|
|
66335
|
+
...intent.source !== "none" ? { additionalContext: { "codex-for-love.message-time": inputTimeContext(intent.source, now()) } } : {}
|
|
66104
66336
|
});
|
|
66105
66337
|
intent.turnId = response.turnId;
|
|
66106
66338
|
mergeTurnInputIds(response.turnId, intent.ids);
|
|
@@ -66155,7 +66387,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66155
66387
|
ids,
|
|
66156
66388
|
input: intents.map((intent) => intent.input).join("\n"),
|
|
66157
66389
|
images: intents.flatMap((intent) => intent.images),
|
|
66158
|
-
transportId: clientIdForInputs(ids)
|
|
66390
|
+
transportId: clientIdForInputs(ids),
|
|
66391
|
+
source: intents.every((intent) => intent.source === "owner") ? "owner" : "none"
|
|
66159
66392
|
};
|
|
66160
66393
|
recoveryPromise = (async () => {
|
|
66161
66394
|
try {
|
|
@@ -66192,7 +66425,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66192
66425
|
ids: [first.id],
|
|
66193
66426
|
input: payload.input,
|
|
66194
66427
|
images: payload.images,
|
|
66195
|
-
transportId: first.id
|
|
66428
|
+
transportId: first.id,
|
|
66429
|
+
source: "keet"
|
|
66196
66430
|
});
|
|
66197
66431
|
} catch (error) {
|
|
66198
66432
|
if (!closing) processError("keet.admission_failed", error, { operationId: first.id });
|
|
@@ -66289,7 +66523,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66289
66523
|
ids: unconsumed,
|
|
66290
66524
|
input: "",
|
|
66291
66525
|
images: [],
|
|
66292
|
-
transportId: "restore"
|
|
66526
|
+
transportId: "restore",
|
|
66527
|
+
source: "none"
|
|
66293
66528
|
});
|
|
66294
66529
|
}
|
|
66295
66530
|
async function interruptActiveTurn() {
|
|
@@ -66372,6 +66607,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66372
66607
|
break;
|
|
66373
66608
|
}
|
|
66374
66609
|
case "turn/started": {
|
|
66610
|
+
pet?.turnStarted();
|
|
66375
66611
|
const turn = registerTurn(params.turn);
|
|
66376
66612
|
if (turn) {
|
|
66377
66613
|
const reconciled = userItems(turn).length || sourceIdsForTurn(turn.id).length ? await reconcileTurn(turn.id) : turn;
|
|
@@ -66383,6 +66619,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66383
66619
|
}
|
|
66384
66620
|
case "item/started": {
|
|
66385
66621
|
const item = record(params.item);
|
|
66622
|
+
pet?.itemStarted(item);
|
|
66386
66623
|
const turnId = typeof params.turnId === "string" ? params.turnId : "";
|
|
66387
66624
|
if (turnId && item.type === "imageGeneration") {
|
|
66388
66625
|
mergeItem(turnId, item);
|
|
@@ -66400,6 +66637,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66400
66637
|
}
|
|
66401
66638
|
case "item/completed": {
|
|
66402
66639
|
const item = record(params.item);
|
|
66640
|
+
pet?.itemCompleted(item);
|
|
66403
66641
|
const turnId = typeof params.turnId === "string" ? params.turnId : "";
|
|
66404
66642
|
if (turnId) mergeItem(turnId, item);
|
|
66405
66643
|
if (turnId && [
|
|
@@ -66419,6 +66657,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66419
66657
|
}
|
|
66420
66658
|
case "turn/completed": {
|
|
66421
66659
|
const turn = registerTurn(params.turn);
|
|
66660
|
+
pet?.turnCompleted(turn?.status);
|
|
66422
66661
|
let reconciled = turn;
|
|
66423
66662
|
if (turn && (userItems(turn).length || sourceIdsForTurn(turn.id).length)) {
|
|
66424
66663
|
reconciled = await reconcileTurn(turn.id);
|
|
@@ -66678,6 +66917,9 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66678
66917
|
}
|
|
66679
66918
|
},
|
|
66680
66919
|
avatar: (kind) => avatars[kind],
|
|
66920
|
+
async petAsset(activity) {
|
|
66921
|
+
return pet ? localPetClip(config.state, activity) : void 0;
|
|
66922
|
+
},
|
|
66681
66923
|
async snapshot(options = {}) {
|
|
66682
66924
|
await eventChain;
|
|
66683
66925
|
const page = options.after === void 0 ? visibleHistoryPage(await store.allMessages(), [...turnResults.values()], options.before) : await store.messagePage(options);
|
|
@@ -66734,7 +66976,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66734
66976
|
voices: result.voiceIds.map((id) => ({
|
|
66735
66977
|
id,
|
|
66736
66978
|
url: `/api/audio/${id}.mp3`
|
|
66737
|
-
}))
|
|
66979
|
+
})),
|
|
66980
|
+
...result.completedAt === void 0 ? {} : { completedAt: result.completedAt }
|
|
66738
66981
|
}));
|
|
66739
66982
|
const unresolved = await unresolvedMessages();
|
|
66740
66983
|
const context = await store.observedContext();
|
|
@@ -66766,6 +67009,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66766
67009
|
pendingCount: pendingIds.size,
|
|
66767
67010
|
cancellable,
|
|
66768
67011
|
typing: activeTurnId !== null,
|
|
67012
|
+
...pet ? { pet: pet.snapshot() } : {},
|
|
66769
67013
|
messages,
|
|
66770
67014
|
results,
|
|
66771
67015
|
draft: restoredDraft ? {
|
|
@@ -66804,7 +67048,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66804
67048
|
ids: [id],
|
|
66805
67049
|
input,
|
|
66806
67050
|
images: materialized,
|
|
66807
|
-
transportId: id
|
|
67051
|
+
transportId: id,
|
|
67052
|
+
source: "owner"
|
|
66808
67053
|
};
|
|
66809
67054
|
if (activeTurnId) await steerIntent(intent, activeTurnId);
|
|
66810
67055
|
else await startIntent(intent);
|
|
@@ -66877,6 +67122,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66877
67122
|
close() {
|
|
66878
67123
|
if (closePromise) return closePromise;
|
|
66879
67124
|
closing = true;
|
|
67125
|
+
pet?.close();
|
|
66880
67126
|
if (keetReconnect) clearTimeout(keetReconnect);
|
|
66881
67127
|
keetFeed?.close();
|
|
66882
67128
|
for (const unsubscribe of unsubscribeAppServer.splice(0)) unsubscribe();
|
|
@@ -67674,6 +67920,22 @@ function createWebServer(partner, assets, options = {}) {
|
|
|
67674
67920
|
response.end(avatar.data);
|
|
67675
67921
|
return;
|
|
67676
67922
|
}
|
|
67923
|
+
if (path.startsWith("/api/pet-assets/") && request.method === "GET") {
|
|
67924
|
+
const activity = path.slice(16);
|
|
67925
|
+
if (!PET_ACTIVITIES.includes(activity)) return json(response, { error: "Pet asset not found" }, 404);
|
|
67926
|
+
const asset = await partner.petAsset(activity);
|
|
67927
|
+
if (!asset) return json(response, { error: "Pet asset not found" }, 404);
|
|
67928
|
+
const metadata = asset.manifest.clips[activity];
|
|
67929
|
+
response.writeHead(200, {
|
|
67930
|
+
"content-type": "image/webp",
|
|
67931
|
+
"cache-control": "no-store",
|
|
67932
|
+
"x-pet-frame-count": String(metadata.frameCount),
|
|
67933
|
+
"x-pet-fps": String(metadata.fps),
|
|
67934
|
+
"x-pet-loop": String(metadata.loop)
|
|
67935
|
+
});
|
|
67936
|
+
response.end(asset.data);
|
|
67937
|
+
return;
|
|
67938
|
+
}
|
|
67677
67939
|
if (path === "/api/messages" && request.method === "POST") {
|
|
67678
67940
|
const parsed = object({
|
|
67679
67941
|
id: uuid(),
|
|
@@ -22708,7 +22708,8 @@ const schema = object({
|
|
|
22708
22708
|
keet: object({
|
|
22709
22709
|
endpoint: string().min(1).optional(),
|
|
22710
22710
|
media_root: string().min(1).optional()
|
|
22711
|
-
}).strict().optional()
|
|
22711
|
+
}).strict().optional(),
|
|
22712
|
+
pet: object({ enabled: boolean().default(false) }).strict().default({ enabled: false })
|
|
22712
22713
|
}).strict();
|
|
22713
22714
|
async function loadConfig(path) {
|
|
22714
22715
|
const config = schema.parse(parse(await readFile(path, "utf8")));
|