Compare commits
3
Commits
e5d271bc45
...
7f5131e92f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f5131e92f | ||
|
|
28e0decbc3 | ||
|
|
2c2031469e |
No files matched your search
@@ -4,6 +4,11 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Integrated Through
|
||||
|
||||
- 2026-09-22:原老师集成任务后续将修复源 `28e0decbc34c10cd69c9261d554aed448bb8e145` 从 `e5d271b` 快进合入本地 `main`。
|
||||
修复发布定义中默认思考强度 `effort=null` 被当作具体强度而误报不可用的问题,旧话题可继续使用其固定版本;显式强度与真实不支持选项的校验保持。
|
||||
源复现测试先失败,修复后 25 项相关测试、类型检查、scoped lint 与 Vite 全目标构建通过;合并产品树与已测源完全一致。
|
||||
用户确认发布关闭思考后新建话题可用;当前修复尚未推送、打包或安装,不代表现有安装版已更新。见[集成记录](tasks/20260922-merge-coding-teacher-client-b80c376f.md)和[修复源记录](tasks/20260922-teacher-unavailable-6d8fa721.md)。
|
||||
|
||||
- 2026-09-22:集成任务 `20260922-merge-coding-teacher-client-b80c376f` 以 `00ad84c` 合入教师源 `9242a40d874984159d71494ac6510f3a248e89c0`,保留当前永久点数钱包。
|
||||
项目自动创建默认 Agent,会话直接位于项目下;右侧老师按云端发布配置独立答疑,回答可追加主草稿。
|
||||
唯一 Sidebar 引用冲突保留项目切换引用及主线钱包行为;合并代码 112 项相关单测、Renderer typecheck、Vite 全目标构建与 3 项 Electron 流程通过。
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
## Outcome
|
||||
|
||||
- Follow-up: fast-forwarded main from e5d271b to 28e0decbc34c10cd69c9261d554aed448bb8e145, including prior source diagnosis commit 2c20314 and the unchanged source task record. Teacher wire DTO now represents nullable effort; model preparation canonicalizes null/missing default strength before validation. Topic definitions remain pinned, no data or Operations migration. User confirmed the new-topic workaround works.
|
||||
- Merged source 9242a40d874984159d71494ac6510f3a248e89c0 into main in 00ad84c, preserving main permanent wallet source a1cce42. Only conflict was Sidebar refs: retain projectEntryIntentRef, do not reintroduce removed tokenPointRequestIdRef/resetCardRequestIdRef. README auto-merge retains both features.
|
||||
- Promoted accepted project/default-Agent/teacher contracts; amended ADR-008 old first-Agent entry using the already-approved product decision. Source task record imported unchanged.
|
||||
- User authorized old wallet recovery: renamed the invalid residual directory to D:/Datas/OthersProjects/.codex-worktrees/makelore/20260922-permanent-points-client-7f4c9a2e-recovery-backup, preserving all contents and its node_modules junction. Official release-missing cleared the exact stale reservation; integration claim then succeeded.
|
||||
@@ -36,6 +37,7 @@
|
||||
|
||||
## Verification
|
||||
|
||||
- Follow-up: latest source ancestry and clean/committed Ready for Integration status confirmed. After fast-forward, git diff 28e0dec -- electron shared src tests returned empty. Reuse exact-source 25 teacher/model regression tests, Renderer typecheck, scoped ESLint and Vite full build from the preceding turn; no new product code or merge conflict justified repeating them. Review the actual merged code and task-aware documentation drift to catch import or ownership mistakes.
|
||||
- Primary pnpm typecheck initially failed because tsc was absent from the existing primary dependency directory; no product diagnostic ran there.
|
||||
- Copied the resolved merged Git index to C:/Users/7brot/AppData/Local/Temp/teacher-merge-client-20260922-b80c376f, linked source-verified dependencies, then completed all checks before source cleanup: 112 relevant unit tests (teacher service/UI, workspace/project entry/schema/conversation store, wallet/sidebar/billing client/routes), pnpm run typecheck and pnpm run build:vite passed.
|
||||
- Three real Electron scenarios passed on that merged build: teacher answer appends the main draft without submission; first PI Conversation editable under 500 ms and submits before Snapshot; wallet reopens unpaid frozen order and refreshes only after confirmed credit. Controlled local responses, no real payment/model charge.
|
||||
@@ -46,6 +48,8 @@
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Reasoning-fix source checkout 20260922-teacher-unavailable-6d8fa721 at D:/Datas/OthersProjects/.codex-worktrees/makelore/20260922-teacher-unavailable-6d8fa721, branch codex/20260922-teacher-unavailable-6d8fa721-teacher-unavailable: user explicitly approved cleanup. Official retire failed with Directory not empty even with process-local Git core.longpaths=true; the Git marker and worktree registration were gone, while 2,996 dependency Junctions and file residuals remained. A bounded native residual-delete attempt was rejected before execution by automatic approval (blocked by policy, no more detail). No deletion retry or policy workaround was attempted. Preserved all residual bytes in the same-parent 20260922-teacher-unavailable-6d8fa721-recovery-backup directory, then official release-missing succeeded. Source branch still resolves to 28e0dec. Cleanup is partial: registry released, backup retained. No cleanup requested for the separate server read-only contract task or old backups.
|
||||
- The running installed app still needs a release containing 28e0dec; this follow-up performs local main integration only, without push/package/install or paid model verification.
|
||||
- No remote push, installer or deployment. Pair with server 93ece7c6; migrate 0095 then configure/test/publish/enable teacher and verify real gateway billing.
|
||||
- Keep both client recovery-backup directories. The teacher checkout cleanup is partial: its registered worktree is released, residual backup retained. Removing backup bytes is not claimed as completed.
|
||||
- Existing primary dependency directory is incomplete; validation used isolated dependencies. Reinstalling the primary development environment is separate work.
|
||||
@@ -53,3 +57,12 @@
|
||||
## Promotion Candidates
|
||||
|
||||
- Applied the user-approved source candidates in integration mode; no unresolved teacher product decision remains.
|
||||
|
||||
## Teacher reasoning fix integration follow-up
|
||||
|
||||
- User confirms new teacher topic works and explicitly requests fixing the old-topic error; continue this same teacher integration task for source 28e0dec, without changing topic-version policy.
|
||||
- Project Context Loaded: official same-task integration resume/status Passed on main at e5d271b; identity, original base 0cf67be, absolute primary worktree and exclusive integration lock match. Read own/source records and entry; reuse unchanged teacher ADR and required memory, architecture/domain/evidence/reflection/commitment context loaded during this conversation. Read 123 peer task records, 17 unknown placeholder scopes; no concrete semantic conflict. Source task is clean and Ready for Integration.
|
||||
- Planning Gate Passed. Main is the exact source base, so integrate with fast-forward; source product verification remains applicable. Preserve the three adopted foreign docs unchanged and exclude them from commits. No subagents, remote push, deployment, installed-file changes or paid calls.
|
||||
- Plan: import the exact tested fix, record integrated provenance and default-effort semantics, check task-document boundaries, commit/complete and offer source checkout cleanup separately.
|
||||
|
||||
- Follow-up Task Documentation Gate: inspected source-to-main product equality, provenance and clean imported source record; task-aware drift passed with the original three foreign documents unchanged. Only current-state and this integration record are committed for the follow-up.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Task: Diagnose coding teacher unavailable message
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260922-teacher-unavailable-6d8fa721
|
||||
- Mode: Feature
|
||||
- Branch: codex/20260922-teacher-unavailable-6d8fa721-teacher-unavailable
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260922-teacher-unavailable-6d8fa721
|
||||
- Base commit: e5d271bc457b4e91e6bda52a28db4a1ecf91d406
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Explain the screenshot message 老师暂未开放 by tracing its exact UI condition and cloud configuration path. Follow-up now covers the reported reasoning error and a bounded client fix; live Operations state remains read-only.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Project Context Loaded: official check/start/status passed with Identity above, feature mode, isolated managed worktree and base e5d271bc457b4e91e6bda52a28db4a1ecf91d406. 123 owner records read; 17 peer placeholder scopes remain unknown, no concrete conflicting dependency. Packaging 1.6.2 is independent and product-read-only.
|
||||
- Read entry/planning-gate, own record, teacher ADR and integrated state; reuse unchanged memory-index, template positioning, decisions, system/module/data-flow/domain, success criteria and evidence/reflection/commitment/stale context already loaded during preceding integration. Project goal remains Electron/Main-owned coding with independently configured official teacher.
|
||||
- Active constraints: no subagents, no live configuration/production writes, no paid calls, no access to credentials or unrelated peer work. Accepted teacher ADR separates publication from enablement; deployment and live billing are not established by merge.
|
||||
- Planning Gate Passed. Relevant modules: TeacherChatPanel, teacher config client/service and CodingChatPanel mount lifecycle. Current live server enabled status is unknown; screenshot establishes only the last loaded client state.
|
||||
- diagnosing-bugs applied as bounded symptom-condition inspection. This is a behavior question, not an established defect or requested fix; skip reproduction, hypothesis ranking and regression mutation because the exact single UI condition resolves what the message means. Do not claim a live backend root cause without its response.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Confirmed reasoning error root cause: the selected installed-app topic is pinned to published v1 with mode=enabled and effort=null. Server Pydantic intentionally persists nullable effort; client request validation previously formed effort:null and rejected it as an unavailable native strength. User-reported current Operations disabled selection does not change that existing topic.
|
||||
- Corrected TeacherDefinition's wire type to represent nullable effort, and normalized null/missing enabled effort to the canonical default-strength choice before existing capability validation. Explicit strengths and unsupported-choice rejection remain unchanged; no fallback model, topic migration or capability override.
|
||||
- Immediate installed-version path: save and publish the intended disabled setting as a new version, then create a new teacher topic using +. Reopening the same topic retains its frozen v1. Did not mutate the user's topic or live Operations settings.
|
||||
|
||||
- TeacherChatPanel.tsx:65-68 reads config.enabled; :336-337 renders this exact message only when enabled is false (initial value is true). :383 disables sending under the same condition.
|
||||
- Main definition() forwards /api/coding-teacher/config availability and reads the published definition independently of enabled; restored local topic history may also supply name/avatar. Seeing 编程老师1 does not establish current enablement.
|
||||
- Production createTopic rejects disabled or unpublished status; each send rechecks live availability. Permission/config request failures produce different errors.
|
||||
- Panel config load runs on mount/base/draftRevision only, without a focus/poll refresh. CodingChatPanel conditionally mounts the panel; closing and reopening reloads enabled state. Thus enabling in Operations while the panel stays open can leave the displayed status stale.
|
||||
- Explain Operations must have a published version and enabled switch. If already enabled, close/reopen teacher panel. Did not inspect the user's current live backend response, so unenabled vs stale loaded status remains unverified.
|
||||
|
||||
## Verification
|
||||
|
||||
- Reasoning fix: pnpm exec vitest run tests/unit/coding-teacher-model.test.ts --maxWorkers=1 reproduced the exact user error in prepareTeacherModel for the local topic shape enabled/effort=null: 1 failed, 6 passed before the fix. The real server schema separately emitted JSON null for unspecified effort.
|
||||
- After fix: teacher model/teacher service/managed model capability suites => 25 passed; pnpm run typecheck, scoped ESLint and pnpm run build:vite passed. Cases cover null/missing default strength, disabled, model default, explicit native strength, and rejection of unsupported strength/disabling. Tests run the real model preparation and native request construction with synthetic transport; no external model charge.
|
||||
|
||||
- Read-only exact-path searches and source reads at e5d271b establish setter, message predicate, send disabling, status forwarding and remount behavior. No runtime test executed or production state changed.
|
||||
- Inspected own diff; only this task record is changed. Task-aware documentation drift is checked before completion.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Fix is committed on this feature branch; merge and rebuild/install are still required to update the running app. Live upstream capabilities and an actual model response have not been verified. Existing teacher topics remain pinned to their creation version by design.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- None. This correction brings the client wire boundary into agreement with the existing server schema and accepted default-strength semantics; it does not change canonical teacher behavior.
|
||||
|
||||
## Reasoning error follow-up
|
||||
|
||||
- Same-task official resume/status Passed at unchanged e5d271b base; re-read all 123 peer records, 17 undefined peer scopes remain unknown, no semantic conflict. Required context and teacher ADR unchanged; Planning Gate Passed.
|
||||
- User reports deepseek-flash / disabled in current Operations (not independently fetched live). Read only selected project registration and filtered teacher/provider metadata, without outputting credentials or conversation text: actual local topic v1 persists enabled with effort=null, created 2026-09-22T06:14:37.190Z, zero requests. Local saved model capability supports disabling and deepseek controls; not a fresh server capability response.
|
||||
- Server contract task verifies ReasoningChoice.model_dump(mode="json") includes effort=null. Plan: reproduce prepareTeacherModel with that real wire shape, normalize the teacher wire DTO at model-request preparation, retain capability validation, and verify enabled/default/disabled/native/unsupported cases. No topic-version migration or live configuration mutation.
|
||||
@@ -39,11 +39,16 @@ export async function prepareTeacherModel(account: TeacherAccount, definition: T
|
||||
'老师所用模型暂不可用,请联系运营调整。'
|
||||
);
|
||||
}
|
||||
const savedChoice = definition.model.reasoning_choice;
|
||||
// Published definitions serialize an unspecified effort as null.
|
||||
const choice = savedChoice.mode === 'enabled'
|
||||
? { mode: savedChoice.mode, ...(savedChoice.effort == null ? {} : { effort: savedChoice.effort }) }
|
||||
: { mode: savedChoice.mode };
|
||||
let fields: Record<string, unknown>;
|
||||
try {
|
||||
fields = buildManagedModelRequest(
|
||||
modelId,
|
||||
definition.model.reasoning_choice,
|
||||
choice,
|
||||
capability
|
||||
).reasoningFields;
|
||||
} catch {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { ManagedReasoningChoice } from './managed-model-capabilities';
|
||||
import type { PublicUsage } from './coding-conversation-contracts';
|
||||
|
||||
export interface TeacherDefinition {
|
||||
@@ -17,7 +16,12 @@ export interface TeacherDefinition {
|
||||
instructions_markdown: string;
|
||||
enabled: boolean;
|
||||
}>;
|
||||
model: { model_id: string | null; reasoning_choice: ManagedReasoningChoice };
|
||||
model: {
|
||||
model_id: string | null;
|
||||
reasoning_choice:
|
||||
| { mode: 'default' | 'disabled'; effort?: null }
|
||||
| { mode: 'enabled'; effort?: string | null };
|
||||
};
|
||||
limits: { max_input_tokens: number; max_output_tokens: number };
|
||||
}
|
||||
export interface TeacherAvailability {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// @vitest-environment node
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import * as cloud from '../../electron/coding-teacher/config-client';
|
||||
import * as transport from '../../electron/utils/proxy-fetch';
|
||||
import { prepareTeacherModel } from '../../electron/coding-teacher/model-runner';
|
||||
import type { TeacherDefinition } from '../../shared/coding-teacher';
|
||||
|
||||
const account: cloud.TeacherAccount = {
|
||||
id: '11111111-1111-4111-8111-111111111111',
|
||||
binding: { accountKey: 'teacher-test', epoch: 1 },
|
||||
};
|
||||
|
||||
// JSON round trip reproduces the cloud/durable-topic boundary, including Pydantic nulls.
|
||||
function definition(choice: unknown): TeacherDefinition {
|
||||
return JSON.parse(JSON.stringify({
|
||||
schema_version: 1, teacher_id: 'coding-teacher', name: 'Teacher',
|
||||
description: '', avatar_id: 'avatar-01', welcome_message: '',
|
||||
suggested_questions: [], system_prompt: 'Explain code.', skills: [],
|
||||
model: { model_id: 'deepseek-flash', reasoning_choice: choice },
|
||||
limits: { max_input_tokens: 8000, max_output_tokens: 1500 },
|
||||
}));
|
||||
}
|
||||
|
||||
function setup(canDisable = true) {
|
||||
vi.spyOn(cloud, 'teacherCloudRequest').mockResolvedValue({
|
||||
api_key: 'synthetic-key', base_url: 'https://teacher-model.invalid/v1',
|
||||
models: ['deepseek-flash'],
|
||||
model_capabilities_v2: {
|
||||
schema_version: 2, models: {
|
||||
'deepseek-flash': {
|
||||
input_modalities: ['text', 'image'], output_modalities: ['text'],
|
||||
reasoning: {
|
||||
supported: true, can_disable: canDisable, default_enabled: true,
|
||||
effort_values: ['low', 'high', 'max'], default_effort: 'high',
|
||||
control_format: 'deepseek',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
vi.spyOn(cloud, 'assertTeacherAccount').mockReturnValue(undefined);
|
||||
return vi.spyOn(transport, 'proxyAwareFetch').mockResolvedValue(new Response(
|
||||
'data: {"choices":[{"delta":{"content":"Explanation"},"finish_reason":"stop"}]}\n\ndata: [DONE]\n\n',
|
||||
{ headers: { 'content-type': 'text/event-stream' } },
|
||||
));
|
||||
}
|
||||
|
||||
afterEach(() => vi.restoreAllMocks());
|
||||
|
||||
describe('teacher published reasoning wire contract', () => {
|
||||
it.each([
|
||||
[{ mode: 'enabled', effort: null }, { thinking: { type: 'enabled' } }],
|
||||
[{ mode: 'enabled' }, { thinking: { type: 'enabled' } }],
|
||||
[{ mode: 'disabled', effort: null }, { thinking: { type: 'disabled' } }],
|
||||
[{ mode: 'default', effort: null }, {}],
|
||||
[{ mode: 'enabled', effort: 'high' }, { thinking: { type: 'enabled' }, reasoning_effort: 'high' }],
|
||||
])('prepares saved choice %j and sends its native controls', async (choice, fields) => {
|
||||
const fetch = setup();
|
||||
const prepared = await prepareTeacherModel(account, definition(choice));
|
||||
const onText = vi.fn();
|
||||
await prepared.run([{ role: 'user', content: 'Explain this.' }], new AbortController().signal, onText);
|
||||
expect(onText).toHaveBeenCalledWith('Explanation');
|
||||
const body = JSON.parse(String(fetch.mock.calls[0][1]?.body));
|
||||
expect({
|
||||
...(body.thinking === undefined ? {} : { thinking: body.thinking }),
|
||||
...(body.reasoning_effort === undefined ? {} : { reasoning_effort: body.reasoning_effort }),
|
||||
}).toEqual(fields);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{ mode: 'enabled', effort: 'unsupported' }, true],
|
||||
[{ mode: 'disabled', effort: null }, false],
|
||||
])('keeps rejecting unsupported choice %j', async (choice, canDisable) => {
|
||||
const fetch = setup(Boolean(canDisable));
|
||||
await expect(prepareTeacherModel(account, definition(choice)))
|
||||
.rejects.toThrow('老师所用思考选项已不可用,请联系运营调整。');
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user