@ckanner/flywheel 0.33.0 → 0.34.0
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/CHANGELOG.md +32 -0
- package/README.md +1 -0
- package/README.zh-CN.md +2 -0
- package/THIRD_PARTY_NOTICES.md +5 -1
- package/bin/flywheel-kimi-native-worker.js +5 -0
- package/bin/flywheel.js +8 -1
- package/bin/runtime.js +5 -1
- package/dist/bridge.mjs +89 -7
- package/dist/claude-code-pro-bridge.mjs +55 -6
- package/dist/client.js +107 -10
- package/dist/codex-pro-bridge.mjs +12 -5
- package/dist/control.mjs +1 -1
- package/dist/kimi-native-bridge.mjs +429 -0
- package/dist/kimi-native-runtime.mjs +233 -0
- package/dist/kimi-native-worker.mjs +77 -0
- package/dist/kimi-tower-candidate.mjs +227 -0
- package/dist/machine-worker.mjs +39 -5
- package/dist/managed-lcu.mjs +223 -0
- package/dist/native-doctor.mjs +36 -0
- package/dist/native-jobs.mjs +72 -0
- package/dist/native-policy.mjs +371 -0
- package/dist/native-resources.mjs +144 -0
- package/dist/native.mjs +251 -0
- package/dist/policy.mjs +13 -3
- package/dist/prewarm.mjs +4 -1
- package/dist/protocol.mjs +8 -1
- package/dist/worker.mjs +16 -9
- package/docs/README.md +9 -0
- package/docs/README.zh-CN.md +3 -0
- package/docs/design.md +34 -12
- package/docs/en/claude-code-pro.md +2 -2
- package/docs/en/configuration.md +17 -5
- package/docs/en/contributing.md +5 -3
- package/docs/en/flow-console.md +1 -1
- package/docs/en/getting-started.md +2 -2
- package/docs/en/model-policy.md +2 -2
- package/docs/en/native-capabilities.md +185 -0
- package/docs/en/releasing.md +2 -2
- package/docs/en/session-recovery.md +2 -2
- package/docs/plans/2026-11-13-native-harness-capabilities.en.md +258 -0
- package/docs/plans/2026-11-13-native-harness-capabilities.md +276 -0
- package/docs/plans/README.md +1 -0
- package/docs/validation/2026-11-14-desktop-native-configuration.md +128 -0
- package/docs/validation/2026-11-14-native-harness-implementation.md +215 -0
- package/docs/validation/2026-11-14-published-companions.md +15 -0
- package/docs/validation/2026-11-14-release-0.33.0.md +49 -0
- package/docs/validation/2026-11-14-release-0.33.1.md +78 -0
- package/docs/validation/README.md +4 -0
- package/docs/validation/evidence/2026-11-14-native-harness-candidate.json +255 -0
- package/docs/validation/evidence/2026-11-14-native-harness-sessions.json +6009 -0
- package/docs/validation/evidence/2026-11-14-native-harness-tower-candidate.json +192 -0
- package/docs/zh-CN/claude-code-pro.md +2 -2
- package/docs/zh-CN/configuration.md +21 -8
- package/docs/zh-CN/contributing.md +5 -3
- package/docs/zh-CN/flow-console.md +1 -1
- package/docs/zh-CN/getting-started.md +2 -2
- package/docs/zh-CN/model-policy.md +2 -2
- package/docs/zh-CN/native-capabilities.md +184 -0
- package/docs/zh-CN/releasing.md +2 -2
- package/docs/zh-CN/session-recovery.md +1 -1
- package/native/darwin-amd64/flywheel +0 -0
- package/native/darwin-arm64/flywheel +0 -0
- package/native/linux-amd64/flywheel +0 -0
- package/native/linux-arm64/flywheel +0 -0
- package/native/manifest.json +9 -9
- package/node_modules/dsh-preset-generator/CHANGELOG.md +77 -0
- package/node_modules/dsh-preset-generator/LICENSE +21 -0
- package/node_modules/dsh-preset-generator/README.md +149 -0
- package/node_modules/dsh-preset-generator/docs/README.zh.md +95 -0
- package/node_modules/dsh-preset-generator/package.json +43 -0
- package/node_modules/dsh-preset-generator/src/composition.mjs +150 -0
- package/node_modules/dsh-preset-generator/src/gen-presets.mjs +367 -0
- package/node_modules/dsh-preset-generator/src/policy.mjs +17 -0
- package/node_modules/dsh-subagent-codex-pro/CHANGELOG.md +16 -1
- package/node_modules/dsh-subagent-codex-pro/README.md +57 -4
- package/node_modules/dsh-subagent-codex-pro/assets/native-client.js +118 -0
- package/node_modules/dsh-subagent-codex-pro/cordis.patch.yml +6 -0
- package/node_modules/dsh-subagent-codex-pro/docs/README.zh.md +49 -2
- package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle-validation.md +1 -1
- package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.md +1 -1
- package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.zh.md +1 -1
- package/node_modules/dsh-subagent-codex-pro/docs/machine.md +2 -2
- package/node_modules/dsh-subagent-codex-pro/docs/native-capabilities.md +254 -0
- package/node_modules/dsh-subagent-codex-pro/docs/native-capabilities.zh.md +180 -0
- package/node_modules/dsh-subagent-codex-pro/lib/config.js +56 -0
- package/node_modules/dsh-subagent-codex-pro/lib/config.js.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/desktop-native.js +109 -0
- package/node_modules/dsh-subagent-codex-pro/lib/desktop-native.js.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js +3 -4
- package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/index.js +64 -15
- package/node_modules/dsh-subagent-codex-pro/lib/index.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/jobs.js +6 -2
- package/node_modules/dsh-subagent-codex-pro/lib/jobs.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js +2 -2
- package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js +5 -2
- package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js +11 -0
- package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/machine.js +20 -3
- package/node_modules/dsh-subagent-codex-pro/lib/machine.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/native.js +297 -0
- package/node_modules/dsh-subagent-codex-pro/lib/native.js.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js +11 -1
- package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/run.js +19 -1
- package/node_modules/dsh-subagent-codex-pro/lib/run.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/tool.js +123 -57
- package/node_modules/dsh-subagent-codex-pro/lib/tool.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/config.d.ts +31 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/config.d.ts.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/desktop-native.d.ts +30 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/desktop-native.d.ts.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts +7 -5
- package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts +31 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts +2 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/machine-local.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervision.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts +7 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/native.d.ts +120 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/native.d.ts.map +1 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts +11 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts +11 -0
- package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts +7 -1
- package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/lib/wire.js +34 -6
- package/node_modules/dsh-subagent-codex-pro/lib/wire.js.map +1 -1
- package/node_modules/dsh-subagent-codex-pro/package.json +28 -4
- package/npm/install.js +2 -2
- package/package.json +25 -10
- package/plugins/dsh/KIMI_NATIVE_PROTOCOL.en.md +76 -0
- package/plugins/dsh/KIMI_NATIVE_PROTOCOL.md +76 -0
- package/plugins/dsh/PROTOCOL.md +151 -17
- package/plugins/dsh/README.md +15 -12
- package/plugins/dsh/README.zh-CN.md +8 -8
- package/plugins/dsh/THIRD_PARTY_NOTICES.md +5 -1
- package/plugins/dsh/vendor/README.md +40 -11
- package/plugins/dsh/vendor/chatgpt.json +21 -0
- package/plugins/dsh/vendor/claude-code-pro.json +21 -0
- package/plugins/dsh/vendor/codex-pro.json +13 -8
- package/plugins/dsh/vendor/lcu.json +21 -0
- package/plugins/dsh/vendor/preset-generator.json +16 -0
package/dist/client.js
CHANGED
|
@@ -815,6 +815,53 @@ function Feedback({ control, selection, reconcile, t }) {
|
|
|
815
815
|
!selection.taskDir.trim() && h('p', null, t('taskRequired'))));
|
|
816
816
|
}
|
|
817
817
|
|
|
818
|
+
// Plain-JS external clients supply real schema factories through the public
|
|
819
|
+
// Typert codec contract; src-json is not a valid generated Client input codec.
|
|
820
|
+
function consoleReadCodec(type, parse) {
|
|
821
|
+
return { mode: 'strict', typeSymbol: '@ckanner/flywheel#' + type, create: () => ({ parse }) };
|
|
822
|
+
}
|
|
823
|
+
function consoleReadObject(value, keys, label) {
|
|
824
|
+
if (!record(value) || Object.keys(value).some(key => !keys.includes(key))) throw new Error('Invalid ' + label);
|
|
825
|
+
return value;
|
|
826
|
+
}
|
|
827
|
+
function consoleReadString(value, label) {
|
|
828
|
+
if (typeof value !== 'string' || !value.trim()) throw new Error('Invalid ' + label);
|
|
829
|
+
return value;
|
|
830
|
+
}
|
|
831
|
+
function consoleReadInput(value) {
|
|
832
|
+
consoleReadObject(value, ['action', 'taskDir', 'cwd', 'probe', 'editor', 'packet', 'runId', 'sessionKey', 'delivery'], 'console read request');
|
|
833
|
+
if (!['runs', 'status', 'config', 'config-edit', 'metrics', 'history', 'node', 'delivery', 'doctor'].includes(value.action)) throw new Error('Console Remote accepts reads only');
|
|
834
|
+
const output = { action: value.action };
|
|
835
|
+
for (const key of ['taskDir', 'cwd', 'packet', 'runId', 'sessionKey']) {
|
|
836
|
+
if (value[key] !== undefined) output[key] = consoleReadString(value[key], key);
|
|
837
|
+
}
|
|
838
|
+
if (value.probe !== undefined) {
|
|
839
|
+
if (value.action !== 'doctor' || typeof value.probe !== 'boolean') throw new Error('Invalid doctor probe');
|
|
840
|
+
output.probe = value.probe;
|
|
841
|
+
}
|
|
842
|
+
if (value.action === 'config-edit') {
|
|
843
|
+
consoleReadObject(value.editor, ['scope'], 'configuration scope');
|
|
844
|
+
if (!['global', 'project'].includes(value.editor.scope)) throw new Error('Invalid configuration scope');
|
|
845
|
+
output.editor = { scope: value.editor.scope };
|
|
846
|
+
} else if (value.editor !== undefined) throw new Error('Editor requires config-edit');
|
|
847
|
+
if (value.action === 'delivery') {
|
|
848
|
+
consoleReadObject(value.delivery, ['action', 'headBranch'], 'delivery inspection');
|
|
849
|
+
if (value.delivery.action !== 'inspect') throw new Error('Delivery Remote accepts inspection only');
|
|
850
|
+
output.delivery = { action: 'inspect' };
|
|
851
|
+
if (value.delivery.headBranch !== undefined) output.delivery.headBranch = consoleReadString(value.delivery.headBranch, 'headBranch');
|
|
852
|
+
} else if (value.delivery !== undefined) throw new Error('Delivery requires inspection');
|
|
853
|
+
if (value.action === 'node' ? !/^M\d+-T\d+$/.test(output.packet ?? '') : value.packet !== undefined) throw new Error('Invalid node packet');
|
|
854
|
+
if (value.action === 'history' ? !output.sessionKey : value.sessionKey !== undefined) throw new Error('Invalid history session key');
|
|
855
|
+
if (value.runId !== undefined && (value.action !== 'metrics' || value.runId.length > 128 || /[\0\r\n]/.test(value.runId))) throw new Error('Invalid metrics run ID');
|
|
856
|
+
return output;
|
|
857
|
+
}
|
|
858
|
+
function consoleReadResult(value) {
|
|
859
|
+
consoleReadObject(value, ['result'], 'console read result');
|
|
860
|
+
const result = consoleReadObject(value.result, ['kind', 'text'], 'console result envelope');
|
|
861
|
+
if (!['success', 'error'].includes(result.kind) || typeof result.text !== 'string') throw new Error('Invalid console result envelope');
|
|
862
|
+
return { result: { kind: result.kind, text: result.text } };
|
|
863
|
+
}
|
|
864
|
+
|
|
818
865
|
exports.inject = ['slots', 'remote', 'remote.commands', 'locale'];
|
|
819
866
|
exports.apply = function apply(ctx) {
|
|
820
867
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'flywheel: locales');
|
|
@@ -833,10 +880,25 @@ exports.apply = function apply(ctx) {
|
|
|
833
880
|
const readsReady = ctx.remote.$mount({ package: '@ckanner/flywheel', descriptors: [{
|
|
834
881
|
id: '@ckanner/flywheel#flywheelConsole/read', service: 'flywheelConsole', namespace: 'flywheelConsole', method: 'read',
|
|
835
882
|
invocation: { kind: 'direct' }, parameters: [
|
|
836
|
-
{ name: 'agent', wire: '
|
|
837
|
-
{ name: 'input', wire: 'input', source: 'json', codec:
|
|
838
|
-
], cancellation: { parameter: 'signal' }, result: {
|
|
839
|
-
}] })
|
|
883
|
+
{ name: 'agent', wire: 'agentId', source: 'lookup', lookup: 'agent', codec: consoleReadCodec('SessionId', value => consoleReadString(value, 'sessionId')) },
|
|
884
|
+
{ name: 'input', wire: 'input', source: 'json', codec: consoleReadCodec('ConsoleReadRequest', consoleReadInput) },
|
|
885
|
+
], cancellation: { parameter: 'signal' }, result: { ...consoleReadCodec('ConsoleReadResult', consoleReadResult), decode: consoleReadResult },
|
|
886
|
+
}] }).then(async () => {
|
|
887
|
+
let readConsole;
|
|
888
|
+
// The namespace is installed asynchronously by $mount. Own its consumer in
|
|
889
|
+
// an injected child scope; the outer plugin cannot access undeclared services.
|
|
890
|
+
const consumer = ctx.inject(['remote.flywheelConsole'], scope => {
|
|
891
|
+
readConsole = (sessionId, request) => scope.remote.flywheelConsole.read(sessionId, request);
|
|
892
|
+
});
|
|
893
|
+
try {
|
|
894
|
+
await consumer;
|
|
895
|
+
if (disposed || !readConsole) throw new Error('Flywheel read scope is unavailable');
|
|
896
|
+
return readConsole;
|
|
897
|
+
} catch (error) {
|
|
898
|
+
await consumer.dispose();
|
|
899
|
+
throw error;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
840
902
|
// A missing read capability is a visible error, never a noisy command fallback.
|
|
841
903
|
readsReady.catch(() => {});
|
|
842
904
|
ctx.slots.inject('conversation.view', () => ctx.slots.register({
|
|
@@ -851,7 +913,7 @@ exports.apply = function apply(ctx) {
|
|
|
851
913
|
control = createControl(async request => {
|
|
852
914
|
const value = readReply(await (mutates(request.action) || request.action === 'status' && control?.source.getSnapshot().uncertainty
|
|
853
915
|
? ctx.remote.commands.execute(sessionId, '/flywheel ' + JSON.stringify(request), [])
|
|
854
|
-
: readsReady.then(
|
|
916
|
+
: readsReady.then(readConsole => readConsole(sessionId, request))), request);
|
|
855
917
|
if (Array.isArray(value.runs)) value.runs = value.runs.filter(item => item.hostSessionId === sessionId);
|
|
856
918
|
return value;
|
|
857
919
|
}, pendingOperations, () => disposed);
|
|
@@ -1312,7 +1374,7 @@ function RuntimeDecisionPanel({ ledger, packetID, t }) {
|
|
|
1312
1374
|
|
|
1313
1375
|
function validExecutionPolicyHistory(packet) {
|
|
1314
1376
|
const policy = packet?.['execution-policy'];
|
|
1315
|
-
const binding = value => record(value) && ['harness', 'provider', 'channel', 'model', 'thinking', 'permission', 'sessionMode']
|
|
1377
|
+
const binding = value => record(value) && ['harness', 'provider', 'channel', 'model', 'thinking', 'nativeProfile', 'permission', 'sessionMode']
|
|
1316
1378
|
.every(key => value[key] == null || typeof value[key] === 'string');
|
|
1317
1379
|
return record(packet) && (policy == null || record(policy) &&
|
|
1318
1380
|
(policy.history == null || Array.isArray(policy.history) && policy.history.every(change =>
|
|
@@ -1324,7 +1386,7 @@ function ExecutionPolicyChanges({ packets, packetID, t }) {
|
|
|
1324
1386
|
const changes = Object.entries(packets ?? {}).flatMap(([id, packet]) => !packetID || id === packetID
|
|
1325
1387
|
? (packet['execution-policy']?.history ?? []).map(change => ({ id, change })) : []);
|
|
1326
1388
|
if (!changes.length) return null;
|
|
1327
|
-
const fields = ['harness', 'provider', 'channel', 'model', 'thinking', 'permission', 'sessionMode'];
|
|
1389
|
+
const fields = ['harness', 'provider', 'channel', 'model', 'thinking', 'nativeProfile', 'permission', 'sessionMode'];
|
|
1328
1390
|
const bindingDetails = (binding, label) => h('div', null,
|
|
1329
1391
|
h('p', null, t(label)),
|
|
1330
1392
|
h('dl', { className: css.consoleProperties }, ...fields.filter(field => binding[field]).map(field =>
|
|
@@ -2394,7 +2456,7 @@ function WorkbenchNodeInspector({
|
|
|
2394
2456
|
((chosen.packet && !chosen.stage) || chosen.group) && h(Button, { onClick: () => expand(chosen) }, t(chosen.packet ? 'wbExpand' : 'wbExpandGroup')),
|
|
2395
2457
|
['delivery', 'merge'].includes(chosen.id) && h(DeliveryPanel, { control, selection, run, t }),
|
|
2396
2458
|
binding && h('section', { className: css.inspectorSection }, h('h4', null, t('wbConfiguration')),
|
|
2397
|
-
h('dl', { className: css.consoleProperties }, property(t('consoleProvider'), bindingCaption({ ...binding, model: '' })), property(t('consoleModel'), binding.model), property(t('consoleThinking'), ({off:'cfgEffortOff',minimal:'cfgEffortMinimal',low:'cfgEffortLow',medium:'cfgEffortMedium',high:'cfgEffortHigh',xhigh:'cfgEffortXhigh',max:'cfgEffortMax'})[binding.thinking] ? t(({off:'cfgEffortOff',minimal:'cfgEffortMinimal',low:'cfgEffortLow',medium:'cfgEffortMedium',high:'cfgEffortHigh',xhigh:'cfgEffortXhigh',max:'cfgEffortMax'})[binding.thinking]) : binding.thinking), property(t('permission'), permissionLabels[binding.permission] ? t(permissionLabels[binding.permission]) : binding.permission))),
|
|
2459
|
+
h('dl', { className: css.consoleProperties }, property(t('consoleProvider'), bindingCaption({ ...binding, model: '' })), property(t('consoleModel'), binding.model), property(t('cfgNative'), binding['native-profile'] || binding.nativeProfile), property(t('consoleThinking'), ({off:'cfgEffortOff',minimal:'cfgEffortMinimal',low:'cfgEffortLow',medium:'cfgEffortMedium',high:'cfgEffortHigh',xhigh:'cfgEffortXhigh',max:'cfgEffortMax'})[binding.thinking] ? t(({off:'cfgEffortOff',minimal:'cfgEffortMinimal',low:'cfgEffortLow',medium:'cfgEffortMedium',high:'cfgEffortHigh',xhigh:'cfgEffortXhigh',max:'cfgEffortMax'})[binding.thinking]) : binding.thinking), property(t('permission'), permissionLabels[binding.permission] ? t(permissionLabels[binding.permission]) : binding.permission))),
|
|
2398
2460
|
h('section', { className: css.inspectorSection }, h('h4', null, t('wbSession')),
|
|
2399
2461
|
sessions.length ? sessions.map(([key, value]) => h('article', { key, className: css.sessionSummary },
|
|
2400
2462
|
h('h4', null, (roleLabels[value.role] ? t(roleLabels[value.role]) : value.role) + ' · ' + value.scope),
|
|
@@ -3227,6 +3289,27 @@ function ConfigEditor({ control, selection, run, t, active = false, cache, conte
|
|
|
3227
3289
|
else next[group][key][field] = value;
|
|
3228
3290
|
replace(next);
|
|
3229
3291
|
};
|
|
3292
|
+
const nativeChoices = value => {
|
|
3293
|
+
const inherited = draft.profiles?.[value.profile]?.['native-profile'];
|
|
3294
|
+
const harness = value.harness || draft.profiles?.[value.profile]?.harness;
|
|
3295
|
+
const choices = [['__inherit__', t('consoleInherit') + (inherited ? ' · ' + inherited : '')], ['', t('cfgNativeNone')],
|
|
3296
|
+
...Object.entries(draft['native-profiles'] ?? {}).filter(([, definition]) => definition.harness === harness).map(([name]) => [name, name])];
|
|
3297
|
+
const selected = value['native-profile'];
|
|
3298
|
+
if (selected && !choices.some(([name]) => name === selected)) choices.push([selected, selected]);
|
|
3299
|
+
return choices;
|
|
3300
|
+
};
|
|
3301
|
+
const setNativeProfile = (value, name) => {
|
|
3302
|
+
const next = { ...value };
|
|
3303
|
+
if (name === '__inherit__') delete next['native-profile'];
|
|
3304
|
+
else next['native-profile'] = name;
|
|
3305
|
+
return next;
|
|
3306
|
+
};
|
|
3307
|
+
const inlineNativeProfile = (group, key, name) => {
|
|
3308
|
+
const next = cloneConfig(draft);
|
|
3309
|
+
if (group === 'panel') next['judge-panel'] = setNativeProfile(next['judge-panel'], name);
|
|
3310
|
+
else next[group][key] = setNativeProfile(next[group][key], name);
|
|
3311
|
+
replace(next);
|
|
3312
|
+
};
|
|
3230
3313
|
const saveBinding = () => {
|
|
3231
3314
|
const { group, key, role, value, permission, session } = bindingEdit,
|
|
3232
3315
|
next = cloneConfig(draft);
|
|
@@ -3363,7 +3446,7 @@ function ConfigEditor({ control, selection, run, t, active = false, cache, conte
|
|
|
3363
3446
|
fields = h(React.Fragment, null,
|
|
3364
3447
|
h('p', { className: css.meta }, t('cfgSessionDefault', { mode: t(draft.sessions?.mode === 'scoped' ? 'cfgReuse' : 'cfgFresh') })),
|
|
3365
3448
|
h('div', { className: css.stageTableScroll }, h('table', { className: css.stageTable, 'aria-label': t('cfgModels') },
|
|
3366
|
-
h('thead', null, h('tr', null, ...['cfgModelRole', 'consoleResource', 'consoleModel', 'consoleThinking', 'consoleSession'].map(key => h('th', { key, scope: 'col' }, t(key))))),
|
|
3449
|
+
h('thead', null, h('tr', null, ...['cfgModelRole', 'consoleResource', 'consoleModel', 'consoleThinking', 'cfgNative', 'consoleSession'].map(key => h('th', { key, scope: 'col' }, t(key))))),
|
|
3367
3450
|
h('tbody', null, ...rows.map(([group, key, value]) => {
|
|
3368
3451
|
const role = group === 'routes' ? 'execute' : key;
|
|
3369
3452
|
const sessionChoices = [['inherit', roleSession(role)], ['scoped', t('cfgReuse')], ['fresh', t('cfgFresh')]];
|
|
@@ -3374,9 +3457,11 @@ function ConfigEditor({ control, selection, run, t, active = false, cache, conte
|
|
|
3374
3457
|
h('td', null, h(Button, { disabled: busy, onClick: () => openBinding(group, key, value), 'aria-label': t('cfgEdit') + ' ' + roleName(group, key) }, resourceNames[resourceOf(value)])),
|
|
3375
3458
|
h('td', null, h('input', { className: css.editorInput, value: value.model ?? '', placeholder: value.profile || t('cfgEffortDefault'), disabled: busy, 'aria-label': roleName(group, key) + ' · ' + t('consoleModel'), onChange: e => inlineBinding(group, key, 'model', e.target.value) })),
|
|
3376
3459
|
h('td', null, h('select', { className: css.modeSelect, value: value.thinking ?? '', disabled: busy, 'aria-label': roleName(group, key) + ' · ' + t('consoleThinking'), onChange: e => inlineBinding(group, key, 'thinking', e.target.value) }, ...[...new Set([...Object.keys(efforts), value.thinking ?? ''])].map(effort => h('option', { key: effort, value: effort }, efforts[effort] ?? effort)))),
|
|
3460
|
+
h('td', null, h('select', { className: css.modeSelect, disabled: busy, value: value['native-profile'] ?? '__inherit__', 'aria-label': roleName(group, key) + ' · ' + t('cfgNative'), onChange: e => inlineNativeProfile(group, key, e.target.value) }, ...nativeChoices(value).map(([name, label]) => h('option', { key: name, value: name }, label)))),
|
|
3377
3461
|
h('td', null, ['intake', 'garden'].includes(role) ? t('cfgIndependent') : h('select', { className: css.modeSelect, disabled: busy, value: draft.sessions?.roles?.[role] ?? 'inherit', 'aria-label': roleName(group, key) + ' · ' + t('consoleSession'), onChange: e => inlineBinding(group, key, 'session', e.target.value) }, ...sessionChoices.map(([v, label]) => h('option', { key: v, value: v }, label))), planConflict && h('div', { className: css.settingsHelp }, t('cfgPlanConflict'), h(Button, { disabled: busy, onClick: () => inlineBinding(group, key, 'session', policy) }, t('cfgApplyPolicy')))));
|
|
3378
3462
|
})))),
|
|
3379
|
-
h('p', { className: css.settingsHelp }, t('consoleRouteSession'))
|
|
3463
|
+
h('p', { className: css.settingsHelp }, t('consoleRouteSession')),
|
|
3464
|
+
h('p', { className: css.settingsHelp }, t('cfgNativeHelp')));
|
|
3380
3465
|
if (draft && section === 'jev')
|
|
3381
3466
|
fields = h(
|
|
3382
3467
|
React.Fragment,
|
|
@@ -3689,6 +3774,9 @@ function ConfigEditor({ control, selection, run, t, active = false, cache, conte
|
|
|
3689
3774
|
},
|
|
3690
3775
|
),
|
|
3691
3776
|
),
|
|
3777
|
+
field('binding.native-profile', t('cfgNative'), t('cfgNativeHelp'),
|
|
3778
|
+
select('binding.native-profile', bindingEdit.value['native-profile'] ?? '__inherit__', nativeChoices(bindingEdit.value),
|
|
3779
|
+
name => setBindingEdit(old => ({ ...old, value: setNativeProfile(old.value, name) })))),
|
|
3692
3780
|
field(
|
|
3693
3781
|
'binding.permission',
|
|
3694
3782
|
t('permission'),
|
|
@@ -3769,6 +3857,15 @@ Object.assign(en, {
|
|
|
3769
3857
|
Object.assign(zh, { cfgPlanConflict: 'Plan 旧历史开关与此策略不同', cfgApplyPolicy: '同步此策略' });
|
|
3770
3858
|
Object.assign(en, { cfgPlanConflict: 'The legacy Plan history switch differs', cfgApplyPolicy: 'Align policy' });
|
|
3771
3859
|
|
|
3860
|
+
Object.assign(zh, {
|
|
3861
|
+
cfgNative: '原生能力', cfgNativeNone: '不启用原生能力配置',
|
|
3862
|
+
cfgNativeHelp: '选择与当前后端匹配的能力配置;在高级 JSON 中编辑 native-profiles。JEV 关闭时仍生效,实际可用性以运行回执为准。',
|
|
3863
|
+
});
|
|
3864
|
+
Object.assign(en, {
|
|
3865
|
+
cfgNative: 'Native capabilities', cfgNativeNone: 'No native capability profile',
|
|
3866
|
+
cfgNativeHelp: 'Select a profile for this backend; edit native-profiles in advanced JSON. Profiles work with JEV off. Runtime receipts establish actual availability.',
|
|
3867
|
+
});
|
|
3868
|
+
|
|
3772
3869
|
Object.assign(zh, {
|
|
3773
3870
|
runsDetails: '运行详情',
|
|
3774
3871
|
runsNoReference: '不设置对照',
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Public machine API consumer. Go remains the owner of scheduling and acceptance.
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { validateNativeAdmission } from './machine-worker.mjs';
|
|
4
5
|
|
|
5
|
-
export const ADAPTER = Object.freeze({ package: 'dsh-subagent-codex-pro', version: '0.
|
|
6
|
+
export const ADAPTER = Object.freeze({ package: 'dsh-subagent-codex-pro', version: '0.10.0', protocol: 1 });
|
|
6
7
|
export const LIMITS = Object.freeze({ requestBytes: 1024 * 1024, machineOutputBytes: 1024 * 1024,
|
|
7
8
|
progressBytes: 1024 * 1024, receiptFrameBytes: 8 * 1024 * 1024, admissionMs: 10000 });
|
|
8
9
|
const require = createRequire(import.meta.url);
|
|
@@ -20,7 +21,7 @@ export async function loadAdapter() {
|
|
|
20
21
|
try {
|
|
21
22
|
manifest = require('dsh-subagent-codex-pro/package.json');
|
|
22
23
|
} catch {
|
|
23
|
-
throw new WorkerError('ADAPTER_UNAVAILABLE', 'Install the exact dsh-subagent-codex-pro@0.
|
|
24
|
+
throw new WorkerError('ADAPTER_UNAVAILABLE', 'Install the exact dsh-subagent-codex-pro@0.10.0 dependency with Flywheel');
|
|
24
25
|
}
|
|
25
26
|
if (manifest.name !== ADAPTER.package || manifest.version !== ADAPTER.version) {
|
|
26
27
|
throw new WorkerError('ADAPTER_MISMATCH', 'Codex Pro package identity or version does not match the pinned contract');
|
|
@@ -31,7 +32,9 @@ export async function loadAdapter() {
|
|
|
31
32
|
typeof api.parseMachineRequest !== 'function' || typeof api.runMachine !== 'function' || typeof api.MachineInputError !== 'function' ||
|
|
32
33
|
api.MACHINE_LIFECYCLE_VERSION !== 1 || typeof api.recoverMachine !== 'function' ||
|
|
33
34
|
api.MACHINE_LIFECYCLE_CAPABILITIES?.durableJournal !== true || api.MACHINE_LIFECYCLE_CAPABILITIES?.readOnlyRecovery !== true ||
|
|
34
|
-
api.MACHINE_LIFECYCLE_CAPABILITIES?.threadReadyBeforeDispatch !== true
|
|
35
|
+
api.MACHINE_LIFECYCLE_CAPABILITIES?.threadReadyBeforeDispatch !== true ||
|
|
36
|
+
api.MACHINE_NATIVE_VERSION !== 1 || api.MACHINE_NATIVE_CAPABILITIES?.version !== 1 ||
|
|
37
|
+
api.MACHINE_NATIVE_CAPABILITIES?.agents !== true || api.MACHINE_NATIVE_CAPABILITIES?.review !== true) {
|
|
35
38
|
throw new WorkerError('ADAPTER_MISMATCH', 'Codex Pro package identity, version or public machine API does not match the pinned contract');
|
|
36
39
|
}
|
|
37
40
|
return api;
|
|
@@ -41,7 +44,7 @@ export async function loadAdapter() {
|
|
|
41
44
|
export function machineRequest(value, api, env) {
|
|
42
45
|
const lifecycle = value?.protocol === 3;
|
|
43
46
|
const persistent = value?.protocol === 2 || (lifecycle && value.threadMode === 'persistent');
|
|
44
|
-
const keys = new Set(['type', 'protocol', 'requestId', 'cwd', 'model', 'reasoningEffort', 'permissionMode', 'prompt', 'timeoutMs',
|
|
47
|
+
const keys = new Set(['type', 'protocol', 'requestId', 'cwd', 'model', 'reasoningEffort', 'permissionMode', 'prompt', 'timeoutMs', 'native', 'managed', 'images', 'outputSchema',
|
|
45
48
|
...(persistent || lifecycle ? ['threadMode', 'threadId'] : []), ...(lifecycle ? ['recoveryDirectory'] : [])]);
|
|
46
49
|
if (value === null || typeof value !== 'object' || Array.isArray(value) || value.type !== 'start' || ![1, 2, 3].includes(value.protocol) ||
|
|
47
50
|
Object.keys(value).some(key => !keys.has(key)) || typeof value.requestId !== 'string' || value.requestId.length > 256 ||
|
|
@@ -56,11 +59,15 @@ export function machineRequest(value, api, env) {
|
|
|
56
59
|
if (value.timeoutMs !== undefined && (!Number.isSafeInteger(value.timeoutMs) || value.timeoutMs < 1 || value.timeoutMs > 2147483647)) {
|
|
57
60
|
throw new WorkerError('INVALID_REQUEST', 'timeoutMs must be a positive safe integer no greater than 2147483647');
|
|
58
61
|
}
|
|
62
|
+
validateNativeAdmission(value.managed, value.requestId, WorkerError);
|
|
59
63
|
try {
|
|
60
64
|
return api.parseMachineRequest({ protocol: 1, requestId: value.requestId, cwd: value.cwd, model: value.model,
|
|
61
65
|
effort: value.reasoningEffort,
|
|
62
66
|
permissionMode: value.permissionMode === 'danger-full-access' ? 'dangerously-bypass-approvals-and-sandbox' : value.permissionMode,
|
|
63
67
|
prompt: value.prompt,
|
|
68
|
+
...(value.native === undefined ? {} : { native: value.native }),
|
|
69
|
+
...(value.images === undefined ? {} : { images: value.images }),
|
|
70
|
+
...(value.outputSchema === undefined ? {} : { outputSchema: value.outputSchema }),
|
|
64
71
|
...(value.timeoutMs === undefined ? {} : { timeoutMs: value.timeoutMs }),
|
|
65
72
|
command: env.FLYWHEEL_CODEX_BIN || 'codex', threadMode: persistent ? 'persistent' : 'ephemeral',
|
|
66
73
|
...(persistent && value.threadId !== undefined ? { threadId: value.threadId } : {}), maxOutputBytes: LIMITS.machineOutputBytes });
|
|
@@ -71,5 +78,5 @@ export function machineRequest(value, api, env) {
|
|
|
71
78
|
|
|
72
79
|
export function doctorResult() {
|
|
73
80
|
return { protocol: 1, type: 'doctor', package: ADAPTER.package, version: ADAPTER.version,
|
|
74
|
-
machineProtocol: ADAPTER.protocol, available: true, inferenceTested: false };
|
|
81
|
+
machineProtocol: ADAPTER.protocol, nativeVersion: 1, available: true, inferenceTested: false };
|
|
75
82
|
}
|
package/dist/control.mjs
CHANGED
|
@@ -73,7 +73,7 @@ function validConfiguration(value) {
|
|
|
73
73
|
Array.isArray(value.bindings) && value.bindings.every(binding => record(binding) &&
|
|
74
74
|
['id', 'role', 'harness'].every(key =>
|
|
75
75
|
typeof binding[key] === 'string' && binding[key].trim() !== '') &&
|
|
76
|
-
['route', 'profile', 'provider', 'channel', 'model', 'thinking', 'permissionMode'].every(key =>
|
|
76
|
+
['route', 'profile', 'nativeProfile', 'provider', 'channel', 'model', 'thinking', 'permissionMode'].every(key =>
|
|
77
77
|
binding[key] === undefined || typeof binding[key] === 'string') &&
|
|
78
78
|
['residentSession', 'inScope'].every(key => binding[key] === undefined || typeof binding[key] === 'boolean'));
|
|
79
79
|
}
|