feat(coding): add model tools and device packages

This commit is contained in:
2026-09-02 18:35:26 +08:00
parent 841273b433
commit 664b8823a0
60 changed files with 3847 additions and 2068 deletions

View File

@@ -8,6 +8,14 @@ import type {
RuntimeContextDetailsV1,
TaskStateDetailsV1,
} from './coding-conversation-contracts';
import type { ModelToolDetailsV1, ModelWebSearchErrorCode } from './model-tools';
import {
DEVICE_PACKAGE_TOOL_NAMES,
type DevicePackageIndexV1,
type DevicePackageRecordV1,
type DevicePackageToolDetailsV1,
type InstallPreviewV1,
} from './device-packages';
import { DATA_SERVICE_PI_TOOL_NAMES } from './data-service';
const PRODUCT_TOOL_NAMES = new Set([
@@ -17,6 +25,8 @@ const PRODUCT_TOOL_NAMES = new Set([
'task_state',
'changed_file',
'runtime_context',
'web_search',
...DEVICE_PACKAGE_TOOL_NAMES,
...DATA_SERVICE_PI_TOOL_NAMES,
]);
@@ -239,6 +249,7 @@ function capabilityDetails(value: Record<string, unknown>): CapabilityResultV1 |
|| value.schema !== 'makelore-capability.v1') return null;
if (typeof value.plugin_id !== 'string' || value.plugin_id.length > 48
|| !CAPABILITY_PLUGIN_ID_PATTERN.test(value.plugin_id)
|| value.plugin_id === 'makelore.web-search'
|| !text(value.plugin_version, 64)
|| typeof value.capability_id !== 'string' || !CAPABILITY_ID_PATTERN.test(value.capability_id)
|| typeof value.operation !== 'string' || !CAPABILITY_OPERATION_PATTERN.test(value.operation)
@@ -298,6 +309,186 @@ function capabilityDetails(value: Record<string, unknown>): CapabilityResultV1 |
};
}
const MODEL_WEB_SEARCH_ERROR_CONTRACT = Object.freeze({
model_web_search_unsupported: { httpStatus: 400, retryable: false },
model_context_changed: { httpStatus: 409, retryable: false },
model_web_search_rate_limited: { httpStatus: 429, retryable: false },
model_web_search_unavailable: { httpStatus: 503, retryable: true },
model_web_search_invalid_result: { httpStatus: 502, retryable: false },
} satisfies Record<ModelWebSearchErrorCode, { httpStatus: number; retryable: boolean }>);
function modelToolSource(value: unknown): { title: string; url: string } | null {
const source = record(value);
const title = text(source?.title, 240);
const rawUrl = text(source?.url, 2_048);
if (!source || !exactKeys(source, ['title', 'url']) || !title || !rawUrl) return null;
try {
const url = new URL(rawUrl);
if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password) return null;
return { title, url: url.toString() };
} catch {
return null;
}
}
function modelToolDetails(value: Record<string, unknown>): ModelToolDetailsV1 | null {
if (value.schema !== 'makelore-model-tool.v1' || value.tool !== 'web_search') return null;
const modelId = text(value.modelId, 256);
if (!modelId) return null;
if (value.status === 'succeeded') {
if (!exactKeys(value, [
'schema', 'tool', 'status', 'modelId', 'answer', 'sources', 'sourceMode',
])) return null;
const answer = text(value.answer, 20_000);
if (!answer || !Array.isArray(value.sources) || value.sources.length > 20
|| (value.sourceMode !== 'structured' && value.sourceMode !== 'inline-or-structured')) return null;
const sources = value.sources.map(modelToolSource);
if (sources.some((source) => source === null)
|| (value.sourceMode === 'structured' && sources.length === 0)) return null;
return {
schema: 'makelore-model-tool.v1',
tool: 'web_search',
status: 'succeeded',
modelId,
answer,
sources: sources as Array<{ title: string; url: string }>,
sourceMode: value.sourceMode,
};
}
if (value.status !== 'failed'
|| !exactKeys(value, ['schema', 'tool', 'status', 'modelId', 'error'])) return null;
const error = record(value.error);
const code = error?.code;
const contract = typeof code === 'string'
? MODEL_WEB_SEARCH_ERROR_CONTRACT[code as ModelWebSearchErrorCode]
: undefined;
const message = text(error?.message, 2_000);
if (!error || !contract || !message
|| !exactKeys(error, ['code', 'message', 'httpStatus', 'retryable'])
|| error.httpStatus !== contract.httpStatus
|| error.retryable !== contract.retryable) return null;
return {
schema: 'makelore-model-tool.v1',
tool: 'web_search',
status: 'failed',
modelId,
error: {
code: code as ModelWebSearchErrorCode,
message,
httpStatus: contract.httpStatus as 400 | 409 | 429 | 502 | 503,
retryable: contract.retryable,
},
};
}
function deviceSkillEntries(value: unknown): DevicePackageRecordV1['skillEntries'] | null {
if (!Array.isArray(value) || value.length > 100) return null;
const entries: Array<{ id: string; entryPath: string }> = [];
for (const candidate of value) {
const item = record(candidate);
const id = text(item?.id, 128);
const entryPath = text(item?.entryPath, 1_024);
if (!item || !exactKeys(item, ['id', 'entryPath']) || !id || !entryPath) return null;
entries.push({ id, entryPath });
}
return entries;
}
function devicePackageKind(value: unknown): DevicePackageRecordV1['kind'] | null {
return value === 'skill-only' || value === 'pi-extension' || value === 'mixed' ? value : null;
}
function devicePackagePreview(value: unknown): InstallPreviewV1 | null {
const preview = record(value);
if (!preview || !exactKeys(preview, [
'schemaVersion', 'planId', 'expiresAt', 'requestedSource', 'resolvedSource',
'packageId', 'displayName', 'resolvedVersion', 'kind', 'skillEntries',
'extensionEntries', 'includesExecutableCode', 'ignoredLifecycleScripts', 'warnings',
'scope',
]) || preview.schemaVersion !== 1 || preview.scope !== 'device-parent-workers'
|| typeof preview.includesExecutableCode !== 'boolean') return null;
const planId = text(preview.planId, 128);
const expiresAt = text(preview.expiresAt, 64);
const requestedSource = text(preview.requestedSource, 2_048);
const resolvedSource = text(preview.resolvedSource, 4_096);
const packageId = text(preview.packageId, 128);
const displayName = text(preview.displayName, 240);
const resolvedVersion = text(preview.resolvedVersion, 128);
const kind = devicePackageKind(preview.kind);
const skillEntries = deviceSkillEntries(preview.skillEntries);
const extensionEntries = strings(preview.extensionEntries, 100);
const ignoredLifecycleScripts = strings(preview.ignoredLifecycleScripts, 20);
const warnings = strings(preview.warnings, 20);
if (!planId || !expiresAt || !requestedSource || !resolvedSource || !packageId
|| !displayName || !resolvedVersion || !kind || !skillEntries || !extensionEntries
|| !ignoredLifecycleScripts || !warnings) return null;
return {
schemaVersion: 1, planId, expiresAt, requestedSource, resolvedSource, packageId,
displayName, resolvedVersion, kind, skillEntries, extensionEntries,
includesExecutableCode: preview.includesExecutableCode,
ignoredLifecycleScripts, warnings, scope: 'device-parent-workers',
};
}
function devicePackageRecord(value: unknown): DevicePackageRecordV1 | null {
const item = record(value);
if (!item || !exactKeys(item, [
'schemaVersion', 'packageId', 'displayName', 'resolvedVersion', 'source', 'kind',
'skillEntries', 'extensionEntries', 'enabled', 'confirmedExecutableCode', 'installedAt',
]) || item.schemaVersion !== 1 || typeof item.enabled !== 'boolean'
|| typeof item.confirmedExecutableCode !== 'boolean') return null;
const source = record(item.source);
const packageId = text(item.packageId, 128);
const displayName = text(item.displayName, 240);
const resolvedVersion = text(item.resolvedVersion, 128);
const kind = devicePackageKind(item.kind);
const installedAt = text(item.installedAt, 64);
const skillEntries = deviceSkillEntries(item.skillEntries);
const extensionEntries = strings(item.extensionEntries, 100);
if (!source || !exactKeys(source, ['kind', 'requested', 'resolved'])
|| !['npm', 'git', 'file'].includes(String(source.kind))
|| !packageId || !displayName || !resolvedVersion || !kind || !installedAt
|| !skillEntries || !extensionEntries) return null;
const requested = text(source.requested, 2_048);
const resolved = text(source.resolved, 4_096);
if (!requested || !resolved) return null;
return {
schemaVersion: 1, packageId, displayName, resolvedVersion,
source: { kind: source.kind as DevicePackageRecordV1['source']['kind'], requested, resolved },
kind, skillEntries, extensionEntries, enabled: item.enabled,
confirmedExecutableCode: item.confirmedExecutableCode, installedAt,
};
}
function devicePackageIndex(value: unknown): DevicePackageIndexV1 | null {
const index = record(value);
if (!index || !exactKeys(index, ['schemaVersion', 'generation', 'packages'])
|| index.schemaVersion !== 1 || !Number.isSafeInteger(index.generation)
|| (index.generation as number) < 0 || !Array.isArray(index.packages)
|| index.packages.length > 200) return null;
const packages = index.packages.map(devicePackageRecord);
if (packages.some((item) => item === null)) return null;
return { schemaVersion: 1, generation: index.generation as number, packages: packages as DevicePackageRecordV1[] };
}
function devicePackageDetails(value: Record<string, unknown>): DevicePackageToolDetailsV1 | null {
if (value.schema !== 'makelore-device-package.v1' || value.success !== true
|| !['prepare', 'commit', 'list', 'set_enabled', 'uninstall'].includes(String(value.operation))) return null;
if (value.operation === 'prepare') {
if (!exactKeys(value, ['schema', 'operation', 'success', 'preview'])) return null;
const preview = devicePackagePreview(value.preview);
return preview ? { schema: 'makelore-device-package.v1', operation: 'prepare', success: true, preview } : null;
}
if (!exactKeys(value, ['schema', 'operation', 'success', 'index'])) return null;
const index = devicePackageIndex(value.index);
return index ? {
schema: 'makelore-device-package.v1',
operation: value.operation as Exclude<DevicePackageToolDetailsV1['operation'], 'prepare'>,
success: true,
index,
} : null;
}
export function productToolDetails(value: unknown): Exclude<KnownToolDetails, { schema: 'subagent.v1' | 'write-lease.v1' }> | null {
const details = record(value);
if (!details) return null;
@@ -310,6 +501,8 @@ export function productToolDetails(value: unknown): Exclude<KnownToolDetails, {
if (details.schema === 'game-assets.v1') return gameAssetDetails(details);
if (details.schema === 'runtime-context.v1') return runtimeContextDetails(details);
if (details.schema === 'makelore-capability.v1') return capabilityDetails(details);
if (details.schema === 'makelore-model-tool.v1') return modelToolDetails(details);
if (details.schema === 'makelore-device-package.v1') return devicePackageDetails(details);
return null;
}