mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-26 19:36:35 +08:00
273b1ea3cf
Reconcile migration branches without rewriting published revisions; retain additive Codex, monitoring, provider and platform fixes. Keep dynamic runner schemas and Host ownership, restore compatibility regressions, and preserve safe model-test error handling.
113 lines
3.1 KiB
JavaScript
113 lines
3.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import test from 'node:test';
|
|
import ts from 'typescript';
|
|
|
|
const read = (path) => fs.readFileSync(new URL(path, import.meta.url), 'utf8');
|
|
|
|
test('dynamic form combines manifest normalization and shared condition helpers', () => {
|
|
const source = read(
|
|
'../../src/app/home/components/dynamic-form/DynamicFormComponent.tsx',
|
|
);
|
|
const parsed = ts.createSourceFile(
|
|
'DynamicFormComponent.tsx',
|
|
source,
|
|
ts.ScriptTarget.Latest,
|
|
true,
|
|
ts.ScriptKind.TSX,
|
|
);
|
|
assert.equal(
|
|
parsed.parseDiagnostics.length,
|
|
0,
|
|
'Dynamic form must parse after the merge',
|
|
);
|
|
const imports = parsed.statements.filter(ts.isImportDeclaration);
|
|
const importedNames = (module) =>
|
|
imports
|
|
.filter((item) => item.moduleSpecifier.text === module)
|
|
.flatMap(
|
|
(item) =>
|
|
item.importClause?.namedBindings?.elements?.map(
|
|
(entry) => entry.name.text,
|
|
) ?? [],
|
|
);
|
|
assert.ok(
|
|
importedNames('./DynamicFormItemConfig').includes(
|
|
'parseDynamicFormItemType',
|
|
),
|
|
);
|
|
assert.deepEqual(importedNames('./DynamicFormConditions').sort(), [
|
|
'resolveDisabledState',
|
|
'resolveShowIfValue',
|
|
]);
|
|
assert.equal(
|
|
parsed.statements.filter(
|
|
(item) =>
|
|
ts.isFunctionDeclaration(item) &&
|
|
item.name?.text === 'resolveShowIfValue',
|
|
).length,
|
|
0,
|
|
);
|
|
});
|
|
|
|
test('pipeline defaults retain plugin runner containers, not retired Core runners', () => {
|
|
const config = JSON.parse(
|
|
read('../../../src/langbot/templates/default-pipeline-config.json'),
|
|
);
|
|
assert.deepEqual(config.ai, {
|
|
runner: { id: '', 'expire-time': 0 },
|
|
runner_config: {},
|
|
});
|
|
const metadata = read(
|
|
'../../../src/langbot/templates/metadata/pipeline/ai.yaml',
|
|
);
|
|
assert.doesNotMatch(
|
|
metadata,
|
|
/^\s+- name: (?:local-agent|n8n-service-api|langflow-api)$/m,
|
|
);
|
|
assert.match(metadata, /RunnerRegistry/);
|
|
});
|
|
|
|
test('pipeline UI does not restore host-owned Box scope as local-agent config', () => {
|
|
const source = read(
|
|
'../../src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx',
|
|
);
|
|
assert.doesNotMatch(
|
|
source,
|
|
/getBoxScopeContext|force_box_session_id_template|N8nAuthFormComponent/,
|
|
);
|
|
assert.match(source, /ai\.runner_config/);
|
|
assert.match(source, /systemContext=\{dynamicFormSystemContext\}/);
|
|
});
|
|
|
|
test('backend client preserves complementary Codex and runner debug API imports', () => {
|
|
const source = read('../../src/app/infra/http/BackendClient.ts');
|
|
const parsed = ts.createSourceFile(
|
|
'BackendClient.ts',
|
|
source,
|
|
ts.ScriptTarget.Latest,
|
|
true,
|
|
);
|
|
assert.equal(
|
|
parsed.parseDiagnostics.length,
|
|
0,
|
|
'API client must parse after the merge',
|
|
);
|
|
const imports = parsed.statements
|
|
.filter(ts.isImportDeclaration)
|
|
.flatMap(
|
|
(item) =>
|
|
item.importClause?.namedBindings?.elements?.map(
|
|
(entry) => entry.name.text,
|
|
) ?? [],
|
|
);
|
|
for (const name of [
|
|
'CodexAuthStatus',
|
|
'CodexDeviceAuthorization',
|
|
'CodexDevicePoll',
|
|
'DebugExecutionEvent',
|
|
]) {
|
|
assert.ok(imports.includes(name), name);
|
|
}
|
|
});
|