feat: integrate automatic game resource delivery

This commit is contained in:
2026-09-06 09:50:49 +08:00
parent f721966f3c
commit 4df4bc9624
20 changed files with 1667 additions and 191 deletions

View File

@@ -1,7 +1,7 @@
import path from 'node:path';
import { atomicWriteText } from '../../../coding-projects/atomic-json';
export const MAKELORE_PI_EXTENSION_VERSION = 5;
export const MAKELORE_PI_EXTENSION_VERSION = 6;
export const MAKELORE_PI_EXTENSION_FILENAME = `makelore-runtime-v${MAKELORE_PI_EXTENSION_VERSION}.mjs`;
const BUNDLE_SOURCE = String.raw`
@@ -180,15 +180,78 @@ export function createMakeloreRuntime(runtimeDefaults = {}) {
return response.result;
}
function registerProductTool(name, label, description, parameters, projectWriteLease = false) {
async function invokeProductStream(toolCallId, toolName, input, signal, onUpdate) {
const context = await runtimeContext();
const bridgeUrl = runtimeValue(RUNTIME_FLAGS.bridgeUrl);
const workerToken = runtimeValue(RUNTIME_FLAGS.workerToken);
if (!bridgeUrl || !workerToken) throw new Error('Makelore runtime bridge is unavailable');
const response = await fetch(bridgeUrl, {
method: 'POST',
headers: {
authorization: 'Bearer ' + workerToken,
'content-type': 'application/json',
},
body: JSON.stringify({
...context,
action: 'product.invoke.stream',
resourceId: toolCallId,
toolName,
input,
}),
signal,
});
if (!response.ok) {
const result = await response.json().catch(() => ({}));
throw new Error(result.error || 'Makelore runtime bridge rejected the request');
}
if (!response.body) throw new Error('Makelore product stream returned no body');
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffered = '';
let finalResult;
let completed = false;
while (true) {
const { value, done } = await reader.read();
buffered += decoder.decode(value || new Uint8Array(), { stream: !done });
let newline = buffered.indexOf('\n');
while (newline >= 0) {
const line = buffered.slice(0, newline);
buffered = buffered.slice(newline + 1);
if (line) {
const item = JSON.parse(line);
if (typeof item.error === 'string') throw new Error(item.error);
if (item.result) {
finalResult = item.result;
if (item.done) completed = true;
else onUpdate?.(item.result);
}
}
newline = buffered.indexOf('\n');
}
if (done) break;
}
if (!completed || !finalResult) throw new Error('Makelore product stream ended before completion');
return finalResult;
}
function registerProductTool(
name,
label,
description,
parameters,
projectWriteLease = false,
streamsProgress = false,
) {
pi.registerTool({
name,
label,
description,
parameters,
...(projectWriteLease ? { executionMode: 'sequential' } : {}),
async execute(toolCallId, params, signal) {
return await invokeProduct(toolCallId, name, params, signal);
async execute(toolCallId, params, signal, onUpdate) {
return streamsProgress
? await invokeProductStream(toolCallId, name, params, signal, onUpdate)
: await invokeProduct(toolCallId, name, params, signal);
},
});
}
@@ -229,6 +292,7 @@ export function createMakeloreRuntime(runtimeDefaults = {}) {
declaration.description,
declaration.inputSchema,
dynamicLeaseTools.has(declaration.name),
declaration.executionMode === 'job',
);
}
}