Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/desktop/e2e/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ async function seedE2eInvocableSkills(userDataDir: string): Promise<void> {
mkdir(path.join(projectSkillRoot, 'project-only'), { recursive: true }),
mkdir(path.join(projectSkillRoot, 'host-incompatible'), { recursive: true }),
mkdir(path.join(projectSkillRoot, 'agent-write'), { recursive: true }),
mkdir(path.join(projectSkillRoot, 'deep-research-only'), { recursive: true }),
mkdir(path.join(projectSkillRoot, 'unavailable-tool'), { recursive: true }),
mkdir(path.join(workspaceSkillRoot, 'workspace-only'), { recursive: true }),
mkdir(path.join(userSkillRoot, 'user-only'), { recursive: true }),
]);
Expand All @@ -303,8 +303,8 @@ async function seedE2eInvocableSkills(userDataDir: string): Promise<void> {
'utf8',
),
writeFile(
path.join(projectSkillRoot, 'deep-research-only', 'SKILL.md'),
`---\nname: Deep Research Only\ndescription: Requires a tool available only in Deep Research mode.\nrequired-tools: [deep_research_status]\n---\n# Deep Research Only`,
path.join(projectSkillRoot, 'unavailable-tool', 'SKILL.md'),
`---\nname: Unavailable Tool\ndescription: Requires a tool unavailable on this Host.\nrequired-tools: [unavailable_fixture_tool]\n---\n# Unavailable Tool`,
'utf8',
),
writeFile(
Expand Down
59 changes: 7 additions & 52 deletions apps/desktop/renderer-architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"src/renderer/app-shell-project-actions.ts",
"src/renderer/app-shell-revision-actions.ts",
"src/renderer/app-shell-session-events.ts",
"src/renderer/app-shell-session-start-actions.ts",
"src/renderer/app-shell-session-ui-state.ts",
"src/renderer/app-shell-stop-action.ts",
"src/renderer/app-shell-turn-actions.ts",
Expand Down Expand Up @@ -208,7 +207,6 @@
"src/renderer/use-app-shell-session-list.ts",
"src/renderer/use-app-shell-session-ui-reads.ts",
"src/renderer/use-app-shell-session-workspace.ts",
"src/renderer/use-deep-research-run.ts",
"src/renderer/use-new-task-choice.ts",
"src/renderer/use-onboarding-snapshot.ts",
"src/renderer/use-project-context.ts",
Expand Down Expand Up @@ -381,7 +379,7 @@
"react": 1
},
"importSpecifiers": 8,
"nonTriviaTokens": 2234
"nonTriviaTokens": 2189
},
"src/renderer/app-shell-context-compaction.ts": {
"importDeclarations": 0,
Expand Down Expand Up @@ -605,27 +603,6 @@
"importSpecifiers": 7,
"nonTriviaTokens": 2687
},
"src/renderer/app-shell-session-start-actions.ts": {
"importDeclarations": 2,
"bridgePaths": {
"window.maka.newTasks.create": 1,
"window.maka.onboarding.setMilestone": 1
},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [
"createAppShellSessionStartActions"
],
"dependencyPaths": {
"./locales/shell-copy.js": 1,
"./model-connection-errors.js": 1,
"./session-workspace-errors.js": 1
},
"importSpecifiers": 5,
"nonTriviaTokens": 650
},
"src/renderer/app-shell-session-ui-state.ts": {
"importDeclarations": 0,
"bridgePaths": {},
Expand Down Expand Up @@ -704,7 +681,7 @@
"nonTriviaTokens": 1245
},
"src/renderer/app-shell.tsx": {
"importDeclarations": 63,
"importDeclarations": 62,
"bridgePaths": {
"window.maka.attachments": 1,
"window.maka.attachments.readBytes": 1,
Expand All @@ -727,7 +704,7 @@
},
"environmentCapabilities": {
"window.clearTimeout": 1,
"window.requestAnimationFrame": 4,
"window.requestAnimationFrame": 3,
"window.setTimeout": 1
},
"hookCalls": {
Expand All @@ -748,7 +725,7 @@
"useNewTaskChoice": 1,
"useOnboardingSnapshot": 1,
"usePlanModeState": 1,
"useRef": 16,
"useRef": 15,
"useSessionCollaborationDialog": 1,
"useSessionEventHealthPolling": 1,
"useSessionNavigationReads": 1,
Expand All @@ -760,7 +737,7 @@
"useShellMemoryPill": 1,
"useShellResume": 1,
"useShellRunUpdates": 1,
"useStableActions": 6,
"useStableActions": 5,
"useState": 13,
"useSystemUiLocale": 1,
"useTaskSubmissionReadiness": 1,
Expand All @@ -782,7 +759,6 @@
"./app-shell-overlays": 1,
"./app-shell-revision-actions": 1,
"./app-shell-session-events": 1,
"./app-shell-session-start-actions": 1,
"./app-shell-stop-action": 1,
"./app-shell-turn-actions": 1,
"./app-shell-turn-view-model": 1,
Expand Down Expand Up @@ -853,8 +829,8 @@
"@maka/ui": 1,
"react": 1
},
"importSpecifiers": 99,
"nonTriviaTokens": 12970
"importSpecifiers": 98,
"nonTriviaTokens": 12840
},
"src/renderer/use-app-shell-composer-quotes.ts": {
"importDeclarations": 0,
Expand Down Expand Up @@ -1095,7 +1071,6 @@
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {
"useDeepResearchRun": 1,
"useExternalStoreSelector": 2,
"useState": 1,
"useUiLocale": 1
Expand All @@ -1109,9 +1084,7 @@
"./features/conversation/index.js": 1,
"./locales/shell-copy": 1,
"./onboarding-hero": 1,
"./use-deep-research-run": 1,
"@astryxdesign/core": 1,
"@maka/core/deep-research": 1,
"@maka/ui": 1,
"react": 1
}
Expand Down Expand Up @@ -3894,23 +3867,6 @@
"react": 1
}
},
"src/renderer/use-deep-research-run.ts": {
"bridgePaths": {
"window.maka.deepResearch.get": 1,
"window.maka.deepResearch.subscribeChanges": 1
},
"environmentCapabilities": {},
"hookCalls": {
"useEffect": 1,
"useState": 1
},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"react": 1
}
},
"src/renderer/use-new-task-choice.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down Expand Up @@ -4421,7 +4377,6 @@
"targetZone": "features/conversation",
"legacyPaths": [
"src/renderer/app-shell-chat-actions.ts",
"src/renderer/app-shell-session-start-actions.ts",
"src/renderer/use-app-shell-composer-quotes.ts"
]
},
Expand Down
34 changes: 10 additions & 24 deletions apps/desktop/src/main/__tests__/create-session-input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import { DEEP_RESEARCH_SESSION_LABEL } from '@maka/core/deep-research';

import { DEFAULT_SESSION_NAME } from '@maka/core/session-name';

Expand Down Expand Up @@ -59,24 +58,15 @@ describe('resolveCreateSessionRequest', () => {
});

it('passes a product mode through verbatim for the Host to expand', () => {
assert.deepEqual(resolve({ mode: 'deep_research' }), {
mode: 'deep_research',
assert.deepEqual(resolve({ mode: 'bot' }), {
mode: 'bot',
collaborationMode: 'agent',
orchestrationMode: 'default',
name: DEFAULT_SESSION_NAME,
labels: undefined,
});
});

/**
* `explore` is a boundary a mode confers, never one a caller may open a
* session at — core names the pickable set `ChatDefaultPermissionMode`.
* Without this refusal the seed is only a default: a renderer could ask for
* `explore` outright and get it without the Deep Research label, tools or
* system prompt that define the mode. `sessions:setPermissionMode` stays the
* separate, deliberate path for moving an EXISTING session (the quote
* companion relies on it), so the guard belongs on creation only.
*/
it('refuses a directly-requested explore boundary', () => {
assert.throws(() => resolve({ permissionMode: 'explore' }), TypeError);
assert.throws(() => resolve({ permissionMode: 'nonsense' }), TypeError);
Expand All @@ -87,23 +77,19 @@ describe('resolveCreateSessionRequest', () => {
assert.throws(() => resolve({ orchestrationMode: 'nonsense' }), TypeError);
});

/**
* The mode is a closed set, exercised with the raw values a renderer can
* actually put on the wire. An unrecognized mode must not reach the Host as
* one — it simply is not a mode.
*/
it('drops an unrecognized mode from the renderer', () => {
it('rejects the retired research workflow', () => {
assert.throws(() => resolve({ mode: 'deep_research' }), /Invalid session start mode/);
});

it('drops other unrecognized modes from the renderer', () => {
for (const mode of ['explore', 'deep-reseach', 'chat', 'admin', '', null, 42, {}]) {
const resolved = resolve({ mode });
assert.equal(resolved.mode, undefined, `mode ${JSON.stringify(mode)} reached the wire`);
assert.equal(resolved.name, DEFAULT_SESSION_NAME);
assert.equal(resolved.labels, undefined);
assert.equal(resolve({ mode }).mode, undefined);
}
});

it("carries the caller's name and labels when no mode overrides them", () => {
const resolved = resolve({ name: 'Release notes', labels: ['pinned', DEEP_RESEARCH_SESSION_LABEL] });
const resolved = resolve({ name: 'Release notes', labels: ['pinned', 'mode:bot'] });
assert.equal(resolved.name, 'Release notes');
assert.deepEqual(resolved.labels, ['pinned', DEEP_RESEARCH_SESSION_LABEL]);
assert.deepEqual(resolved.labels, ['pinned', 'mode:bot']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -493,10 +493,6 @@ test('drives bounded Session domain projections through real UDS framing', async
ok: true,
result: { sessionId: input.sessionId, goal: null },
}),
'deep-research.query': async (input) => ({
ok: true,
result: { kind: 'not_started', sessionId: input.sessionId, revision: 0 },
}),
'runtime.resource.query': async (input) => ({
ok: true,
result: {
Expand Down Expand Up @@ -542,7 +538,6 @@ test('drives bounded Session domain projections through real UDS framing', async
executions: [],
});
assert.equal(await ipc.invoke('goal:get', 'session-1'), null);
assert.equal(await ipc.invoke('deepResearch:get', 'session-1'), undefined);
assert.deepEqual(await ipc.invoke('shell-runs:list', 'session-1'), []);

await client.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,16 +714,16 @@ test('drains an accepted Host-backed Bot turn before closing its generation', as

test('rolls back only candidate-owned IPC after a registration collision', async () => {
const ipc = ipcHarness();
ipc.handle('deepResearch:get', async () => 'embedded');
ipc.handle('todo:read', async () => 'embedded');
const host = connectionHarness('collision');

await assert.rejects(
() => createDesktopRuntimeHostCandidate(host.connection, deps(ipc)),
/duplicate handler: deepResearch:get/,
/duplicate handler: todo:read/,
);

assert.equal(await ipc.invoke('deepResearch:get'), 'embedded');
assert.deepEqual(ipc.channels, ['deepResearch:get']);
assert.equal(await ipc.invoke('todo:read'), 'embedded');
assert.deepEqual(ipc.channels, ['todo:read']);
assert.equal(host.closeCalls, 1);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ test('session creation forwards the caller name for a mode that carries none', a
registerRuntimeHostSessionCatalogIpc(createDeps(creates), ipc as unknown as IpcMain);

await ipc.invoke('sessions:create', { mode: 'bot', name: '飞书 任务' });
await ipc.invoke('sessions:create', { mode: 'deep_research', name: '飞书 任务' });
await assert.rejects(
() => ipc.invoke('sessions:create', { mode: 'deep_research', name: '飞书 任务' }),
/Invalid session start mode/,
);

assert.deepEqual(
creates.map((input) => [input.mode, input.name]),
[
['bot', '飞书 任务'],
['deep_research', '飞书 任务'],
],
);
});
Expand Down
Loading
Loading