@lamplitisles/codex-for-love 0.4.0 → 0.4.2
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.DfSR8oPO.css +2 -0
- package/vendor/build/_app/immutable/assets/2.GU_203nr.css +1 -0
- package/vendor/build/_app/immutable/chunks/BxP8U2lE.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.Di6q1DhK.js +2 -0
- package/vendor/build/_app/immutable/entry/start.CwKZcHfn.js +1 -0
- package/vendor/build/_app/immutable/nodes/0.PSG_XCTv.js +1 -0
- package/vendor/build/_app/immutable/nodes/{1.B1qFIsWm.js → 1.CJlXDQ0m.js} +1 -1
- package/vendor/build/_app/immutable/nodes/2.C7zq-Uwo.js +327 -0
- package/vendor/build/_app/version.json +1 -1
- package/vendor/build/index.html +10 -9
- package/vendor/config.example.toml +8 -0
- package/vendor/runtime/cli.mjs +297 -37
- package/vendor/runtime/companion-mcp.mjs +6 -3
- 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":"1789633167994"}
|
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, viewport-fit=cover" /><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.CwKZcHfn.js" rel="modulepreload">
|
|
4
|
+
<link href="/_app/immutable/chunks/BxP8U2lE.js" rel="modulepreload">
|
|
5
|
+
<link href="/_app/immutable/chunks/CTZw3jzS.js" rel="modulepreload">
|
|
6
|
+
<link href="/_app/immutable/entry/app.Di6q1DhK.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.PSG_XCTv.js" rel="modulepreload">
|
|
9
10
|
|
|
10
|
-
<link href="/_app/immutable/assets/0.
|
|
11
|
+
<link href="/_app/immutable/assets/0.DfSR8oPO.css" rel="stylesheet"></head>
|
|
11
12
|
<body data-sveltekit-preload-data="hover"><div style="display: contents">
|
|
12
13
|
<script>
|
|
13
14
|
{
|
|
14
|
-
|
|
15
|
+
__sveltekit_2pnxow = {
|
|
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.CwKZcHfn.js"),
|
|
23
|
+
import("/_app/immutable/entry/app.Di6q1DhK.js")
|
|
23
24
|
]).then(([kit, app]) => {
|
|
24
25
|
kit.start(app, element);
|
|
25
26
|
});
|
|
@@ -19,8 +19,16 @@ model = "gpt-5.6-luna"
|
|
|
19
19
|
# The installed launcher selects and verifies its matching standalone app-server.
|
|
20
20
|
# A checkout configuration may set command to a verified codex-app-server path.
|
|
21
21
|
# local_compaction = true
|
|
22
|
+
# Number of newest complete text rounds included only after compaction. The
|
|
23
|
+
# default is 10; the 4,000-token soft budget can select fewer long rounds.
|
|
24
|
+
# Restart Partner after changing this value.
|
|
25
|
+
context_round_limit = 10
|
|
22
26
|
# home = "/path/to/a/Codex-home" # omit to use the existing Codex login
|
|
23
27
|
|
|
28
|
+
# Optional browser pet. Disabled by default; restart Partner after changing it.
|
|
29
|
+
#[pet]
|
|
30
|
+
#enabled = true
|
|
31
|
+
|
|
24
32
|
# Optional local Keet-for-Agent gateway. Both fields and a stdin-only `keet`
|
|
25
33
|
# credential enable it; omit either field to keep ordinary local conversation.
|
|
26
34
|
#[keet]
|
package/vendor/runtime/cli.mjs
CHANGED
|
@@ -6203,12 +6203,14 @@ const schema = object({
|
|
|
6203
6203
|
version: literal(SUPPORTED_CODEX_VERSION).default(SUPPORTED_CODEX_VERSION),
|
|
6204
6204
|
home: string().min(1).optional(),
|
|
6205
6205
|
provenance: string().min(1).optional(),
|
|
6206
|
-
local_compaction: boolean().default(false)
|
|
6206
|
+
local_compaction: boolean().default(false),
|
|
6207
|
+
context_round_limit: number$1().int().min(0).default(10)
|
|
6207
6208
|
}).strict().default({
|
|
6208
6209
|
command: "codex-app-server",
|
|
6209
6210
|
model: DEFAULT_CODEX_MODEL,
|
|
6210
6211
|
version: SUPPORTED_CODEX_VERSION,
|
|
6211
|
-
local_compaction: false
|
|
6212
|
+
local_compaction: false,
|
|
6213
|
+
context_round_limit: 10
|
|
6212
6214
|
}),
|
|
6213
6215
|
speech: object({
|
|
6214
6216
|
endpoint: url().default("https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"),
|
|
@@ -6217,7 +6219,8 @@ const schema = object({
|
|
|
6217
6219
|
keet: object({
|
|
6218
6220
|
endpoint: string().min(1).optional(),
|
|
6219
6221
|
media_root: string().min(1).optional()
|
|
6220
|
-
}).strict().optional()
|
|
6222
|
+
}).strict().optional(),
|
|
6223
|
+
pet: object({ enabled: boolean().default(false) }).strict().default({ enabled: false })
|
|
6221
6224
|
}).strict();
|
|
6222
6225
|
async function loadConfig(path) {
|
|
6223
6226
|
const config = schema.parse(parse$2(await readFile(path, "utf8")));
|
|
@@ -62600,6 +62603,8 @@ function partnerPaths(workspace) {
|
|
|
62600
62603
|
audio: join(managedRoot, "audio")
|
|
62601
62604
|
};
|
|
62602
62605
|
}
|
|
62606
|
+
//#endregion
|
|
62607
|
+
//#region apps/partner/runtime/context-bootstrap.ts
|
|
62603
62608
|
const CONTEXT_TOKEN_BUDGET = 4e3;
|
|
62604
62609
|
const hookFileName = "session-start-hook.mjs";
|
|
62605
62610
|
const companionMcpFileName = import.meta.url.endsWith(".mjs") ? "companion-mcp.mjs" : "companion-mcp.ts";
|
|
@@ -62620,7 +62625,7 @@ function finalAgentText(items) {
|
|
|
62620
62625
|
return texts.length ? texts.join("\n\n").trim() : void 0;
|
|
62621
62626
|
}
|
|
62622
62627
|
/** Select newest completed conversational sides without copying tool or image payloads. */
|
|
62623
|
-
function selectTextRounds(turns, budget = CONTEXT_TOKEN_BUDGET, limit =
|
|
62628
|
+
function selectTextRounds(turns, budget = CONTEXT_TOKEN_BUDGET, limit = 10) {
|
|
62624
62629
|
const candidates = [];
|
|
62625
62630
|
for (const turn of turns) {
|
|
62626
62631
|
if (turn.status !== "completed" || !turn.items) continue;
|
|
@@ -62680,6 +62685,10 @@ function shellQuote(value) {
|
|
|
62680
62685
|
function hookCommand(contextPath) {
|
|
62681
62686
|
return `${shellQuote(process.execPath)} ${shellQuote(fileURLToPath(new URL(`./${hookFileName}`, import.meta.url)))} ${shellQuote(contextPath)}`;
|
|
62682
62687
|
}
|
|
62688
|
+
/** A release path changes, but a hook targeting this internal bootstrap remains CFL-owned. */
|
|
62689
|
+
function ownsBootstrapHook(value, contextPath) {
|
|
62690
|
+
return isRecord$1(value) && value.type === "command" && typeof value.command === "string" && value.command.includes(hookFileName) && value.command.includes(shellQuote(contextPath));
|
|
62691
|
+
}
|
|
62683
62692
|
function isRecord$1(value) {
|
|
62684
62693
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
62685
62694
|
}
|
|
@@ -62758,31 +62767,21 @@ async function ensureHookDeclaration(workspace, contextPath, partnerConfigPath,
|
|
|
62758
62767
|
const sessionStart = Array.isArray(hooks.SessionStart) ? hooks.SessionStart : [];
|
|
62759
62768
|
let changed = ensureCompanionMcp(config, workspace, partnerConfigPath);
|
|
62760
62769
|
changed = ensureKeetMcp(config, keetEndpoint) || changed;
|
|
62761
|
-
|
|
62762
|
-
|
|
62763
|
-
|
|
62764
|
-
|
|
62765
|
-
|
|
62766
|
-
|
|
62767
|
-
|
|
62768
|
-
|
|
62769
|
-
|
|
62770
|
-
|
|
62771
|
-
|
|
62772
|
-
|
|
62773
|
-
|
|
62774
|
-
|
|
62775
|
-
};
|
|
62770
|
+
const own = sessionStart.flatMap((group) => isRecord$1(group) && Array.isArray(group.hooks) ? group.hooks.filter((handler) => ownsBootstrapHook(handler, contextPath)).map((handler) => ({
|
|
62771
|
+
group,
|
|
62772
|
+
handler
|
|
62773
|
+
})) : []);
|
|
62774
|
+
const canonical = own.length === 1 && own[0].group.matcher === "startup|compact" && own[0].handler.command === command && own[0].handler.additionalContextLimit === 0;
|
|
62775
|
+
let normalizedGroups = sessionStart;
|
|
62776
|
+
if (!canonical) {
|
|
62777
|
+
normalizedGroups = sessionStart.flatMap((group) => {
|
|
62778
|
+
if (!isRecord$1(group) || !Array.isArray(group.hooks)) return [group];
|
|
62779
|
+
const handlers = group.hooks.filter((handler) => !ownsBootstrapHook(handler, contextPath));
|
|
62780
|
+
return handlers.length ? [{
|
|
62781
|
+
...group,
|
|
62782
|
+
hooks: handlers
|
|
62783
|
+
}] : [];
|
|
62776
62784
|
});
|
|
62777
|
-
if (!groupChanged) return group;
|
|
62778
|
-
changed = true;
|
|
62779
|
-
return {
|
|
62780
|
-
...group,
|
|
62781
|
-
matcher: "startup|compact",
|
|
62782
|
-
hooks: handlers
|
|
62783
|
-
};
|
|
62784
|
-
});
|
|
62785
|
-
if (!own) {
|
|
62786
62785
|
normalizedGroups.push({
|
|
62787
62786
|
matcher: "startup|compact",
|
|
62788
62787
|
hooks: [{
|
|
@@ -65339,6 +65338,217 @@ function processError(event, error, details = {}) {
|
|
|
65339
65338
|
...event === "event.failed" ? {} : { error: redactError(message) }
|
|
65340
65339
|
});
|
|
65341
65340
|
}
|
|
65341
|
+
//#endregion
|
|
65342
|
+
//#region apps/partner/runtime/pet.ts
|
|
65343
|
+
/** The deliberately small, browser-safe representation of companion activity. */
|
|
65344
|
+
const PET_ACTIVITIES = [
|
|
65345
|
+
"idle",
|
|
65346
|
+
"thinking",
|
|
65347
|
+
"read",
|
|
65348
|
+
"work",
|
|
65349
|
+
"replying",
|
|
65350
|
+
"success",
|
|
65351
|
+
"concern"
|
|
65352
|
+
];
|
|
65353
|
+
/**
|
|
65354
|
+
* Converts app-server lifecycle metadata into a finite presentation state.
|
|
65355
|
+
* Never retain item text, arguments, results, paths, commands, or errors here.
|
|
65356
|
+
*/
|
|
65357
|
+
var PetActivityProjection = class {
|
|
65358
|
+
#activity = "idle";
|
|
65359
|
+
#revision = 0;
|
|
65360
|
+
#turnActive = false;
|
|
65361
|
+
#items = /* @__PURE__ */ new Map();
|
|
65362
|
+
#timer;
|
|
65363
|
+
#changed;
|
|
65364
|
+
#durations;
|
|
65365
|
+
constructor(changed = () => {}, durations = {
|
|
65366
|
+
success: 1200,
|
|
65367
|
+
concern: 2e3
|
|
65368
|
+
}) {
|
|
65369
|
+
this.#changed = changed;
|
|
65370
|
+
this.#durations = durations;
|
|
65371
|
+
}
|
|
65372
|
+
snapshot() {
|
|
65373
|
+
return {
|
|
65374
|
+
activity: this.#activity,
|
|
65375
|
+
revision: this.#revision
|
|
65376
|
+
};
|
|
65377
|
+
}
|
|
65378
|
+
close() {
|
|
65379
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
65380
|
+
}
|
|
65381
|
+
idle() {
|
|
65382
|
+
this.#turnActive = false;
|
|
65383
|
+
this.#items.clear();
|
|
65384
|
+
this.#set("idle");
|
|
65385
|
+
}
|
|
65386
|
+
turnStarted() {
|
|
65387
|
+
this.#turnActive = true;
|
|
65388
|
+
this.#set("thinking");
|
|
65389
|
+
}
|
|
65390
|
+
itemStarted(item) {
|
|
65391
|
+
this.#turnActive = true;
|
|
65392
|
+
const activity = activityForItem(item);
|
|
65393
|
+
const id = typeof item.id === "string" ? item.id : `anonymous:${this.#items.size}`;
|
|
65394
|
+
this.#items.set(id, activity);
|
|
65395
|
+
this.#set(activity);
|
|
65396
|
+
}
|
|
65397
|
+
itemCompleted(item) {
|
|
65398
|
+
const id = typeof item.id === "string" ? item.id : void 0;
|
|
65399
|
+
if (id) this.#items.delete(id);
|
|
65400
|
+
if (failedItem(item)) this.#transient("concern", 2e3);
|
|
65401
|
+
else this.#set(this.#current());
|
|
65402
|
+
}
|
|
65403
|
+
turnCompleted(status) {
|
|
65404
|
+
this.#turnActive = false;
|
|
65405
|
+
this.#items.clear();
|
|
65406
|
+
this.#transient([
|
|
65407
|
+
"failed",
|
|
65408
|
+
"cancelled",
|
|
65409
|
+
"interrupted"
|
|
65410
|
+
].includes(String(status)) ? "concern" : "success", [
|
|
65411
|
+
"failed",
|
|
65412
|
+
"cancelled",
|
|
65413
|
+
"interrupted"
|
|
65414
|
+
].includes(String(status)) ? this.#durations.concern : this.#durations.success);
|
|
65415
|
+
}
|
|
65416
|
+
#current() {
|
|
65417
|
+
return [...this.#items.values()].at(-1) ?? (this.#turnActive ? "thinking" : "idle");
|
|
65418
|
+
}
|
|
65419
|
+
#transient(activity, ms) {
|
|
65420
|
+
this.#set(activity);
|
|
65421
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
65422
|
+
this.#timer = setTimeout(() => {
|
|
65423
|
+
this.#timer = void 0;
|
|
65424
|
+
this.#set(this.#current());
|
|
65425
|
+
}, ms);
|
|
65426
|
+
}
|
|
65427
|
+
#set(activity) {
|
|
65428
|
+
if (this.#timer && !["success", "concern"].includes(activity)) {
|
|
65429
|
+
clearTimeout(this.#timer);
|
|
65430
|
+
this.#timer = void 0;
|
|
65431
|
+
}
|
|
65432
|
+
if (this.#activity !== activity) {
|
|
65433
|
+
this.#activity = activity;
|
|
65434
|
+
this.#revision += 1;
|
|
65435
|
+
this.#changed();
|
|
65436
|
+
}
|
|
65437
|
+
}
|
|
65438
|
+
};
|
|
65439
|
+
function activityForItem(item) {
|
|
65440
|
+
switch (item.type) {
|
|
65441
|
+
case "agentMessage": return "replying";
|
|
65442
|
+
case "webSearch":
|
|
65443
|
+
case "web": return "read";
|
|
65444
|
+
case "commandExecution":
|
|
65445
|
+
case "fileChange":
|
|
65446
|
+
case "imageGeneration": return "work";
|
|
65447
|
+
case "mcpToolCall": return activityForMcp(String(item.server ?? ""), String(item.tool ?? ""));
|
|
65448
|
+
default: return "thinking";
|
|
65449
|
+
}
|
|
65450
|
+
}
|
|
65451
|
+
function activityForMcp(server, tool) {
|
|
65452
|
+
if (server === "companion") {
|
|
65453
|
+
if (tool === "read_relationship_history") return "read";
|
|
65454
|
+
if (tool === "send_voice" || tool === "roll_dice") return tool === "send_voice" ? "replying" : "thinking";
|
|
65455
|
+
return "work";
|
|
65456
|
+
}
|
|
65457
|
+
if (server === "keet") return tool === "keet_send_message" || tool === "send_message" ? "replying" : "read";
|
|
65458
|
+
if (server === "web" || server === "openaiDeveloperDocs") return "read";
|
|
65459
|
+
if ([
|
|
65460
|
+
"project",
|
|
65461
|
+
"flicknote",
|
|
65462
|
+
"guion-email",
|
|
65463
|
+
"og",
|
|
65464
|
+
"skill"
|
|
65465
|
+
].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";
|
|
65466
|
+
return "thinking";
|
|
65467
|
+
}
|
|
65468
|
+
function failedItem(item) {
|
|
65469
|
+
return [
|
|
65470
|
+
"failed",
|
|
65471
|
+
"error",
|
|
65472
|
+
"cancelled",
|
|
65473
|
+
"interrupted"
|
|
65474
|
+
].includes(String(item.status));
|
|
65475
|
+
}
|
|
65476
|
+
//#endregion
|
|
65477
|
+
//#region apps/partner/runtime/pet-assets.ts
|
|
65478
|
+
const clip = object({
|
|
65479
|
+
file: string().regex(/^[a-z]+\.webp$/u),
|
|
65480
|
+
frameCount: union([literal(6), literal(8)]),
|
|
65481
|
+
fps: number$1().int().min(1).max(24),
|
|
65482
|
+
loop: boolean()
|
|
65483
|
+
}).strict();
|
|
65484
|
+
const manifestSchema = object({
|
|
65485
|
+
schemaVersion: literal(2),
|
|
65486
|
+
character: literal("shio"),
|
|
65487
|
+
revision: string().min(1).max(80),
|
|
65488
|
+
clips: object(Object.fromEntries(PET_ACTIVITIES.map((a) => [a, clip]))).strict()
|
|
65489
|
+
}).strict();
|
|
65490
|
+
const MAX_SHEET_BYTES = 15e5;
|
|
65491
|
+
async function localPetClip(state, activity) {
|
|
65492
|
+
const root = join(state, "pet-assets");
|
|
65493
|
+
let manifest;
|
|
65494
|
+
try {
|
|
65495
|
+
const parsed = manifestSchema.safeParse(JSON.parse(await readFile(join(root, "manifest.json"), "utf8")));
|
|
65496
|
+
if (!parsed.success) return void 0;
|
|
65497
|
+
manifest = parsed.data;
|
|
65498
|
+
} catch {
|
|
65499
|
+
return;
|
|
65500
|
+
}
|
|
65501
|
+
let selected;
|
|
65502
|
+
for (const candidate of PET_ACTIVITIES) {
|
|
65503
|
+
const data = await readClip(root, manifest.clips[candidate].file, manifest.clips[candidate].frameCount);
|
|
65504
|
+
if (!data) return void 0;
|
|
65505
|
+
if (candidate === activity) selected = data;
|
|
65506
|
+
}
|
|
65507
|
+
return selected ? {
|
|
65508
|
+
data: selected,
|
|
65509
|
+
manifest
|
|
65510
|
+
} : void 0;
|
|
65511
|
+
}
|
|
65512
|
+
function webpDimensions(data) {
|
|
65513
|
+
if (data.length < 20 || Buffer.from(data.subarray(0, 4)).toString() !== "RIFF" || Buffer.from(data.subarray(8, 12)).toString() !== "WEBP") return void 0;
|
|
65514
|
+
for (let offset = 12; offset + 8 <= data.length;) {
|
|
65515
|
+
const type = Buffer.from(data.subarray(offset, offset + 4)).toString();
|
|
65516
|
+
const size = data[offset + 4] | data[offset + 5] << 8 | data[offset + 6] << 16 | data[offset + 7] << 24;
|
|
65517
|
+
const body = offset + 8;
|
|
65518
|
+
if (body + size > data.length) return void 0;
|
|
65519
|
+
if (type === "VP8X" && size >= 10) return {
|
|
65520
|
+
width: 1 + data[body + 4] + (data[body + 5] << 8) + (data[body + 6] << 16),
|
|
65521
|
+
height: 1 + data[body + 7] + (data[body + 8] << 8) + (data[body + 9] << 16)
|
|
65522
|
+
};
|
|
65523
|
+
if (type === "VP8 " && size >= 10 && data[body + 3] === 157 && data[body + 4] === 1 && data[body + 5] === 42) return {
|
|
65524
|
+
width: data[body + 6] | (data[body + 7] & 63) << 8,
|
|
65525
|
+
height: data[body + 8] | (data[body + 9] & 63) << 8
|
|
65526
|
+
};
|
|
65527
|
+
if (type === "VP8L" && size >= 5 && data[body] === 47) return {
|
|
65528
|
+
width: 1 + data[body + 1] + ((data[body + 2] & 63) << 8),
|
|
65529
|
+
height: 1 + (data[body + 2] >> 6) + (data[body + 3] << 2) + ((data[body + 4] & 15) << 10)
|
|
65530
|
+
};
|
|
65531
|
+
offset = body + size + size % 2;
|
|
65532
|
+
}
|
|
65533
|
+
}
|
|
65534
|
+
async function readClip(root, name, frameCount) {
|
|
65535
|
+
if (extname(name) !== ".webp") return void 0;
|
|
65536
|
+
const path = resolve(root, name);
|
|
65537
|
+
if (relative(resolve(root), path).startsWith("..")) return void 0;
|
|
65538
|
+
try {
|
|
65539
|
+
const info = await lstat(path);
|
|
65540
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > MAX_SHEET_BYTES) return void 0;
|
|
65541
|
+
const [actualRoot, actual, data] = await Promise.all([
|
|
65542
|
+
realpath(root),
|
|
65543
|
+
realpath(path),
|
|
65544
|
+
readFile(path)
|
|
65545
|
+
]);
|
|
65546
|
+
const dimensions = webpDimensions(data);
|
|
65547
|
+
return dimensions?.height === 512 && dimensions.width === frameCount * 512 && (actual === actualRoot || actual.startsWith(`${actualRoot}/`)) ? data : void 0;
|
|
65548
|
+
} catch {
|
|
65549
|
+
return;
|
|
65550
|
+
}
|
|
65551
|
+
}
|
|
65342
65552
|
const HISTORY_PAGE_MESSAGES = 50;
|
|
65343
65553
|
/** Match DSH's 50-message history window against CFL's rendered projection. */
|
|
65344
65554
|
function visibleHistoryPage(messages, results, before) {
|
|
@@ -65397,6 +65607,19 @@ function turnTime(value, fallback) {
|
|
|
65397
65607
|
if (number === null) return fallback;
|
|
65398
65608
|
return number > 1e10 ? Math.round(number) : Math.round(number * 1e3);
|
|
65399
65609
|
}
|
|
65610
|
+
function completedTurnTime(value) {
|
|
65611
|
+
const raw = numberOrNull(value);
|
|
65612
|
+
if (raw === null) return void 0;
|
|
65613
|
+
return raw > 1e10 ? Math.round(raw) : Math.round(raw * 1e3);
|
|
65614
|
+
}
|
|
65615
|
+
function inputTimeContext(source, now) {
|
|
65616
|
+
const date = new Date(now);
|
|
65617
|
+
const time = `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
65618
|
+
return {
|
|
65619
|
+
kind: "application",
|
|
65620
|
+
value: `${source === "owner" ? "Current owner input" : "Qualifying Keet input"} received around local ${time}. Trusted delivery metadata; not user-authored text or an instruction.`
|
|
65621
|
+
};
|
|
65622
|
+
}
|
|
65400
65623
|
function textFromUserItem(item) {
|
|
65401
65624
|
if (item.type !== "userMessage" || !Array.isArray(item.content)) return void 0;
|
|
65402
65625
|
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 +65879,9 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65656
65879
|
let keetFeed;
|
|
65657
65880
|
let keetReconnect;
|
|
65658
65881
|
let keetConnecting = false;
|
|
65882
|
+
const pet = config.pet.enabled ? new PetActivityProjection(() => {
|
|
65883
|
+
if (!closing) notify();
|
|
65884
|
+
}) : void 0;
|
|
65659
65885
|
const notify = () => {
|
|
65660
65886
|
for (const listener of listeners) listener();
|
|
65661
65887
|
};
|
|
@@ -65711,7 +65937,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65711
65937
|
}
|
|
65712
65938
|
async function refreshBootstrap() {
|
|
65713
65939
|
const history = (await readRelationshipJournal(paths.relationshipJournal)).reverse();
|
|
65714
|
-
const rounds = selectTextRounds([...turns.values()], CONTEXT_TOKEN_BUDGET,
|
|
65940
|
+
const rounds = selectTextRounds([...turns.values()], CONTEXT_TOKEN_BUDGET, config.codex.context_round_limit);
|
|
65715
65941
|
await writeBootstrapFile(bootstrapPath(paths.workspaceRoot), {
|
|
65716
65942
|
startupPending,
|
|
65717
65943
|
context: formatBootstrapContext(stateFromHistory(history)),
|
|
@@ -65958,6 +66184,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65958
66184
|
const voiceIds = voiceIdsFromTurn(turn);
|
|
65959
66185
|
let resultError = errorFromTurn(turn);
|
|
65960
66186
|
let resultStatus = status;
|
|
66187
|
+
const completedAt = status === "completed" ? completedTurnTime(turn.completedAt) : void 0;
|
|
65961
66188
|
for (const item of turn.items ?? []) {
|
|
65962
66189
|
if (item.type !== "imageGeneration") continue;
|
|
65963
66190
|
const generatedId = await projectGeneratedImage(resultOperationId(turn.id), sourceIds, item);
|
|
@@ -65974,7 +66201,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
65974
66201
|
error: resultError,
|
|
65975
66202
|
status: resultStatus,
|
|
65976
66203
|
generatedIds,
|
|
65977
|
-
voiceIds
|
|
66204
|
+
voiceIds,
|
|
66205
|
+
...completedAt === void 0 ? {} : { completedAt }
|
|
65978
66206
|
};
|
|
65979
66207
|
const fingerprint = JSON.stringify(resultBody);
|
|
65980
66208
|
const previous = presentationFingerprints.get(turn.id);
|
|
@@ -66056,7 +66284,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66056
66284
|
const turn = registerTurn((await appServer.call("turn/start", {
|
|
66057
66285
|
threadId,
|
|
66058
66286
|
input: nativeInput(intent.input, intent.images),
|
|
66059
|
-
clientUserMessageId: intent.transportId
|
|
66287
|
+
clientUserMessageId: intent.transportId,
|
|
66288
|
+
...intent.source !== "none" ? { additionalContext: { "codex-for-love.message-time": inputTimeContext(intent.source, now()) } } : {}
|
|
66060
66289
|
})).turn, intent.ids);
|
|
66061
66290
|
if (!turn) throw new Error("Codex app-server did not return a turn");
|
|
66062
66291
|
intent.turnId = turn.id;
|
|
@@ -66100,7 +66329,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66100
66329
|
threadId,
|
|
66101
66330
|
input: nativeInput(intent.input, intent.images),
|
|
66102
66331
|
clientUserMessageId: intent.transportId,
|
|
66103
|
-
expectedTurnId: expected
|
|
66332
|
+
expectedTurnId: expected,
|
|
66333
|
+
...intent.source !== "none" ? { additionalContext: { "codex-for-love.message-time": inputTimeContext(intent.source, now()) } } : {}
|
|
66104
66334
|
});
|
|
66105
66335
|
intent.turnId = response.turnId;
|
|
66106
66336
|
mergeTurnInputIds(response.turnId, intent.ids);
|
|
@@ -66155,7 +66385,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66155
66385
|
ids,
|
|
66156
66386
|
input: intents.map((intent) => intent.input).join("\n"),
|
|
66157
66387
|
images: intents.flatMap((intent) => intent.images),
|
|
66158
|
-
transportId: clientIdForInputs(ids)
|
|
66388
|
+
transportId: clientIdForInputs(ids),
|
|
66389
|
+
source: intents.every((intent) => intent.source === "owner") ? "owner" : "none"
|
|
66159
66390
|
};
|
|
66160
66391
|
recoveryPromise = (async () => {
|
|
66161
66392
|
try {
|
|
@@ -66192,7 +66423,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66192
66423
|
ids: [first.id],
|
|
66193
66424
|
input: payload.input,
|
|
66194
66425
|
images: payload.images,
|
|
66195
|
-
transportId: first.id
|
|
66426
|
+
transportId: first.id,
|
|
66427
|
+
source: "keet"
|
|
66196
66428
|
});
|
|
66197
66429
|
} catch (error) {
|
|
66198
66430
|
if (!closing) processError("keet.admission_failed", error, { operationId: first.id });
|
|
@@ -66289,7 +66521,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66289
66521
|
ids: unconsumed,
|
|
66290
66522
|
input: "",
|
|
66291
66523
|
images: [],
|
|
66292
|
-
transportId: "restore"
|
|
66524
|
+
transportId: "restore",
|
|
66525
|
+
source: "none"
|
|
66293
66526
|
});
|
|
66294
66527
|
}
|
|
66295
66528
|
async function interruptActiveTurn() {
|
|
@@ -66372,6 +66605,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66372
66605
|
break;
|
|
66373
66606
|
}
|
|
66374
66607
|
case "turn/started": {
|
|
66608
|
+
pet?.turnStarted();
|
|
66375
66609
|
const turn = registerTurn(params.turn);
|
|
66376
66610
|
if (turn) {
|
|
66377
66611
|
const reconciled = userItems(turn).length || sourceIdsForTurn(turn.id).length ? await reconcileTurn(turn.id) : turn;
|
|
@@ -66383,6 +66617,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66383
66617
|
}
|
|
66384
66618
|
case "item/started": {
|
|
66385
66619
|
const item = record(params.item);
|
|
66620
|
+
pet?.itemStarted(item);
|
|
66386
66621
|
const turnId = typeof params.turnId === "string" ? params.turnId : "";
|
|
66387
66622
|
if (turnId && item.type === "imageGeneration") {
|
|
66388
66623
|
mergeItem(turnId, item);
|
|
@@ -66400,6 +66635,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66400
66635
|
}
|
|
66401
66636
|
case "item/completed": {
|
|
66402
66637
|
const item = record(params.item);
|
|
66638
|
+
pet?.itemCompleted(item);
|
|
66403
66639
|
const turnId = typeof params.turnId === "string" ? params.turnId : "";
|
|
66404
66640
|
if (turnId) mergeItem(turnId, item);
|
|
66405
66641
|
if (turnId && [
|
|
@@ -66419,6 +66655,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66419
66655
|
}
|
|
66420
66656
|
case "turn/completed": {
|
|
66421
66657
|
const turn = registerTurn(params.turn);
|
|
66658
|
+
pet?.turnCompleted(turn?.status);
|
|
66422
66659
|
let reconciled = turn;
|
|
66423
66660
|
if (turn && (userItems(turn).length || sourceIdsForTurn(turn.id).length)) {
|
|
66424
66661
|
reconciled = await reconcileTurn(turn.id);
|
|
@@ -66678,6 +66915,9 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66678
66915
|
}
|
|
66679
66916
|
},
|
|
66680
66917
|
avatar: (kind) => avatars[kind],
|
|
66918
|
+
async petAsset(activity) {
|
|
66919
|
+
return pet ? localPetClip(config.state, activity) : void 0;
|
|
66920
|
+
},
|
|
66681
66921
|
async snapshot(options = {}) {
|
|
66682
66922
|
await eventChain;
|
|
66683
66923
|
const page = options.after === void 0 ? visibleHistoryPage(await store.allMessages(), [...turnResults.values()], options.before) : await store.messagePage(options);
|
|
@@ -66734,7 +66974,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66734
66974
|
voices: result.voiceIds.map((id) => ({
|
|
66735
66975
|
id,
|
|
66736
66976
|
url: `/api/audio/${id}.mp3`
|
|
66737
|
-
}))
|
|
66977
|
+
})),
|
|
66978
|
+
...result.completedAt === void 0 ? {} : { completedAt: result.completedAt }
|
|
66738
66979
|
}));
|
|
66739
66980
|
const unresolved = await unresolvedMessages();
|
|
66740
66981
|
const context = await store.observedContext();
|
|
@@ -66766,6 +67007,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66766
67007
|
pendingCount: pendingIds.size,
|
|
66767
67008
|
cancellable,
|
|
66768
67009
|
typing: activeTurnId !== null,
|
|
67010
|
+
...pet ? { pet: pet.snapshot() } : {},
|
|
66769
67011
|
messages,
|
|
66770
67012
|
results,
|
|
66771
67013
|
draft: restoredDraft ? {
|
|
@@ -66804,7 +67046,8 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66804
67046
|
ids: [id],
|
|
66805
67047
|
input,
|
|
66806
67048
|
images: materialized,
|
|
66807
|
-
transportId: id
|
|
67049
|
+
transportId: id,
|
|
67050
|
+
source: "owner"
|
|
66808
67051
|
};
|
|
66809
67052
|
if (activeTurnId) await steerIntent(intent, activeTurnId);
|
|
66810
67053
|
else await startIntent(intent);
|
|
@@ -66877,6 +67120,7 @@ async function createPartner(config, credentials, dependencies = {}) {
|
|
|
66877
67120
|
close() {
|
|
66878
67121
|
if (closePromise) return closePromise;
|
|
66879
67122
|
closing = true;
|
|
67123
|
+
pet?.close();
|
|
66880
67124
|
if (keetReconnect) clearTimeout(keetReconnect);
|
|
66881
67125
|
keetFeed?.close();
|
|
66882
67126
|
for (const unsubscribe of unsubscribeAppServer.splice(0)) unsubscribe();
|
|
@@ -67674,6 +67918,22 @@ function createWebServer(partner, assets, options = {}) {
|
|
|
67674
67918
|
response.end(avatar.data);
|
|
67675
67919
|
return;
|
|
67676
67920
|
}
|
|
67921
|
+
if (path.startsWith("/api/pet-assets/") && request.method === "GET") {
|
|
67922
|
+
const activity = path.slice(16);
|
|
67923
|
+
if (!PET_ACTIVITIES.includes(activity)) return json(response, { error: "Pet asset not found" }, 404);
|
|
67924
|
+
const asset = await partner.petAsset(activity);
|
|
67925
|
+
if (!asset) return json(response, { error: "Pet asset not found" }, 404);
|
|
67926
|
+
const metadata = asset.manifest.clips[activity];
|
|
67927
|
+
response.writeHead(200, {
|
|
67928
|
+
"content-type": "image/webp",
|
|
67929
|
+
"cache-control": "no-store",
|
|
67930
|
+
"x-pet-frame-count": String(metadata.frameCount),
|
|
67931
|
+
"x-pet-fps": String(metadata.fps),
|
|
67932
|
+
"x-pet-loop": String(metadata.loop)
|
|
67933
|
+
});
|
|
67934
|
+
response.end(asset.data);
|
|
67935
|
+
return;
|
|
67936
|
+
}
|
|
67677
67937
|
if (path === "/api/messages" && request.method === "POST") {
|
|
67678
67938
|
const parsed = object({
|
|
67679
67939
|
id: uuid(),
|
|
@@ -22694,12 +22694,14 @@ const schema = object({
|
|
|
22694
22694
|
version: literal(SUPPORTED_CODEX_VERSION).default(SUPPORTED_CODEX_VERSION),
|
|
22695
22695
|
home: string().min(1).optional(),
|
|
22696
22696
|
provenance: string().min(1).optional(),
|
|
22697
|
-
local_compaction: boolean().default(false)
|
|
22697
|
+
local_compaction: boolean().default(false),
|
|
22698
|
+
context_round_limit: number().int().min(0).default(10)
|
|
22698
22699
|
}).strict().default({
|
|
22699
22700
|
command: "codex-app-server",
|
|
22700
22701
|
model: DEFAULT_CODEX_MODEL,
|
|
22701
22702
|
version: SUPPORTED_CODEX_VERSION,
|
|
22702
|
-
local_compaction: false
|
|
22703
|
+
local_compaction: false,
|
|
22704
|
+
context_round_limit: 10
|
|
22703
22705
|
}),
|
|
22704
22706
|
speech: object({
|
|
22705
22707
|
endpoint: url().default("https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"),
|
|
@@ -22708,7 +22710,8 @@ const schema = object({
|
|
|
22708
22710
|
keet: object({
|
|
22709
22711
|
endpoint: string().min(1).optional(),
|
|
22710
22712
|
media_root: string().min(1).optional()
|
|
22711
|
-
}).strict().optional()
|
|
22713
|
+
}).strict().optional(),
|
|
22714
|
+
pet: object({ enabled: boolean().default(false) }).strict().default({ enabled: false })
|
|
22712
22715
|
}).strict();
|
|
22713
22716
|
async function loadConfig(path) {
|
|
22714
22717
|
const config = schema.parse(parse(await readFile(path, "utf8")));
|