Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
66c59b9
feat(runtime): add GitHub Copilot device-flow enrollment
hgaol Aug 21, 2026
38657e4
feat(desktop): sign in to GitHub Copilot with a device grant
hgaol Aug 21, 2026
d13edc7
fix(runtime,desktop): move Copilot enrollment onto the Host OAuth seam
hgaol Aug 21, 2026
16f6520
fix(desktop): restore the GitHub Copilot sign-in in Settings
hgaol Aug 21, 2026
9fff4c6
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 21, 2026
5530fe2
feat(runtime-host): own GitHub Copilot enrollment end to end
hgaol Aug 21, 2026
7d20e18
fix(desktop): adopt the account's own model inventory after sign-in
hgaol Aug 21, 2026
53a72cb
fix(settings): show the device code on the connection re-login notice
hgaol Aug 22, 2026
bc44d6e
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 22, 2026
b5da959
fix(desktop): open an account on a model its own live list reported
hgaol Aug 22, 2026
51f8282
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 22, 2026
df9b4b4
fix(desktop): let the selected Host decide whether a provider may enroll
hgaol Aug 22, 2026
5619ced
Merge branch 'main' of github.com:apache/maka into feat/github-copilo…
hgaol Aug 22, 2026
49fae7c
fix(runtime): report an unanswered Copilot entitlement check as retry…
hgaol Aug 22, 2026
6c417a5
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 23, 2026
99ac4df
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 23, 2026
0685beb
test(runtime-host): claim the late-request rejection before awaiting …
hgaol Aug 23, 2026
0b9ebaf
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 23, 2026
0cc8898
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 24, 2026
1d460ed
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 24, 2026
85abcaa
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 24, 2026
d2f566c
chore: add missing ASF headers on upstream plugin-composition files
hgaol Aug 24, 2026
a4c1fff
chore: retrigger CI (flaky slash-command-menu e2e test)
hgaol Aug 24, 2026
ab38b1f
Merge remote-tracking branch 'upstream/main' into feat/github-copilot…
hgaol Aug 24, 2026
43cc284
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 24, 2026
55d1c20
fix(runtime-host): move the compatibility epoch off a value other ope…
hgaol Aug 24, 2026
2ff12f7
test(desktop): retarget the Copilot generation story at the Host sign-in
hgaol Aug 24, 2026
a2e6095
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 24, 2026
02ee0bf
docs(astryx): regenerate the surface inventory totals
hgaol Aug 24, 2026
bec8187
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 26, 2026
12844b0
fix(desktop): stand the local import down while a device grant is pol…
hgaol Aug 26, 2026
0dbfd9d
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 26, 2026
f555b2d
Merge branch 'main' of https://github.com/apache/maka into feat/githu…
hgaol Aug 27, 2026
4096d9d
fix(desktop): ask the Host whether Copilot may enrol before offering …
hgaol Aug 27, 2026
6040b19
Merge origin/main and resolve Copilot entitlement feedback
hgaol Aug 30, 2026
fb4ff2f
chore(desktop): refresh renderer architecture ledger
hgaol Aug 30, 2026
766c8cf
Merge origin/main into feat/github-copilot-device-flow-login
hgaol Aug 31, 2026
0574002
fix(storage): admit github-copilot through the interactive OAuth enro…
hgaol Aug 31, 2026
c8c33b6
Merge origin/main into feat/github-copilot-device-flow-login
hgaol Sep 3, 2026
e5d0aea
fix(oauth): restore selected-Host authority after main merge
hgaol Sep 3, 2026
aa6dd35
fix(oauth): adopt local Copilot credentials through the Host
hgaol Sep 3, 2026
aec5dfb
Merge origin/main into feat/github-copilot-device-flow-login
hgaol Sep 3, 2026
6f27b0c
refactor(desktop): route OAuth settings through the feature services …
hgaol Sep 3, 2026
25d49be
chore(desktop): remove obsolete OAuth bridge surface
hgaol Sep 3, 2026
f859b6d
fix(storybook): bind OAuth stories through connection services
hgaol Sep 3, 2026
3f07d3f
Merge origin/main into feat/github-copilot-device-flow-login
hgaol Sep 3, 2026
24ded23
Merge origin/main into feat/github-copilot-device-flow-login
hgaol Sep 3, 2026
9b91ae6
fix(settings): align Copilot entry copy and OAuth fixture contracts
hgaol Sep 3, 2026
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
1 change: 1 addition & 0 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@ant-design/icons-svg": "4.5.0",
"@astryxdesign/core": "0.5.2",
"@astryxdesign/theme-neutral": "0.5.2",
"@babel/parser": "7.29.7",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@fontsource-variable/geist": "^5.3.0",
Expand Down
49 changes: 7 additions & 42 deletions apps/desktop/renderer-architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@
"src/renderer/settings/runtime-host-onboarding-dialog.tsx",
"src/renderer/settings/runtime-host-profiles-section.tsx",
"src/renderer/settings/runtime-host-project-directory-editor.tsx",
"src/renderer/settings/runtime-host-settings-bridge.ts",
"src/renderer/settings/runtime-host-settings-target.tsx",
"src/renderer/settings/runtime-host-ssh-terminal-dialog.tsx",
"src/renderer/settings/settings-error-copy.ts",
Expand Down Expand Up @@ -3409,21 +3408,17 @@
}
},
"src/renderer/settings/provider-connection-detail.tsx": {
"bridgePaths": {
"window.maka.githubCopilotSubscription.connectExistingLogin": 1
},
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {
"useActionGuard": 1,
"useConnectionDetail": 1,
"useEffect": 2,
"useMountedRef": 3,
"useMountedRef": 2,
"useOAuthLoginFlow": 1,
"useRuntimeHostSettingsErrorReporter": 3,
"useRuntimeHostSettingsTarget": 1,
"useRuntimeHostSettingsErrorReporter": 2,
"useState": 8,
"useToast": 2,
"useUiLocale": 4
"useUiLocale": 3
},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
Expand All @@ -3440,7 +3435,6 @@
"./runtime-host-settings-target.js": 1,
"./settings-expandable-row": 1,
"./settings-section": 1,
"./use-action-guard": 1,
"./use-connection-detail": 1,
"./use-oauth-login-flow": 1,
"@astryxdesign/core": 1,
Expand Down Expand Up @@ -3520,23 +3514,13 @@
}
},
"src/renderer/settings/provider-oauth-section.tsx": {
"bridgePaths": {
"window.maka.githubCopilotSubscription.connectExistingLogin": 1,
"window.maka.githubCopilotSubscription.getAccountState": 2,
"window.maka.githubCopilotSubscription.logout": 1,
"window.maka.githubCopilotSubscription.refreshTokens": 1,
"window.maka.openAiCodex": 1,
"window.maka.xaiOAuth": 1
},
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {
"useEffect": 1,
"useMountedRef": 1,
"useOAuthLoginFlow": 2,
"useRef": 1,
"useRuntimeHostSettingsGenerationKey": 1,
"useRuntimeHostSettingsTarget": 3,
"useState": 2,
"useState": 1,
"useUiLocale": 3
},
"lifecycleMethods": {},
Expand All @@ -3545,7 +3529,6 @@
"dependencyPaths": {
"../../preload/bridge-contract.js": 1,
"../features/connection-settings": 1,
"./runtime-host-settings-bridge.js": 1,
"./runtime-host-settings-target.js": 1,
"./use-oauth-login-flow": 1,
"@astryxdesign/core": 1,
Expand Down Expand Up @@ -3770,18 +3753,6 @@
"@maka/ui": 1
}
},
"src/renderer/settings/runtime-host-settings-bridge.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"../../preload/bridge-contract.js": 1,
"./use-oauth-login-flow.js": 1
}
},
"src/renderer/settings/runtime-host-settings-target.tsx": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down Expand Up @@ -4235,18 +4206,14 @@
}
},
"src/renderer/settings/use-connection-detail.ts": {
"bridgePaths": {
"window.maka.openAiCodex": 1,
"window.maka.xaiOAuth": 1
},
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {
"useEffect": 6,
"useKeyedActionGuard": 1,
"useMountedRef": 1,
"useRef": 4,
"useRuntimeHostSettingsErrorReporter": 1,
"useRuntimeHostSettingsTarget": 1,
"useState": 14,
"useToast": 1,
"useUiLocale": 1
Expand All @@ -4255,13 +4222,11 @@
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {
"../../preload/bridge-contract.js": 1,
"../features/connection-settings": 1,
"./connection-name-draft.js": 1,
"./provider-connection-status": 1,
"./relay-profile-draft": 1,
"./relay-thinking-bulk": 1,
"./runtime-host-settings-bridge.js": 1,
"./runtime-host-settings-target.js": 1,
"./use-action-guard": 1,
"./use-oauth-login-flow": 1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';

import { importGitHubCopilotLocalCredential } from '../oauth/github-copilot-local-credential.js';

describe('importGitHubCopilotLocalCredential', () => {
test('prefers an explicit Copilot Requests credential over the generic GitHub CLI login', async () => {
const previous = process.env.COPILOT_GITHUB_TOKEN;
process.env.COPILOT_GITHUB_TOKEN = 'github_pat_copilot_requests';
try {
const imported = await importGitHubCopilotLocalCredential();

assert.deepEqual(JSON.parse(imported.secret ?? ''), {
access_token: 'github_pat_copilot_requests',
refresh_token: 'github_pat_copilot_requests',
expires_at: Number.MAX_SAFE_INTEGER,
token_type: 'Bearer',
base_url: 'https://api.githubcopilot.com',
});
assert.deepEqual(imported.result, { ok: true });
} finally {
if (previous === undefined) delete process.env.COPILOT_GITHUB_TOKEN;
else process.env.COPILOT_GITHUB_TOKEN = previous;
}
});

test('returns credential material without asking GitHub about entitlement', async () => {
let resolutions = 0;
const imported = await importGitHubCopilotLocalCredential({
resolveGitHubToken: async () => {
resolutions += 1;
return 'gho_existing_login\n';
},
});

assert.equal(resolutions, 1);
assert.deepEqual(imported.result, { ok: true });
assert.deepEqual(JSON.parse(imported.secret ?? ''), {
access_token: 'gho_existing_login',
refresh_token: 'gho_existing_login',
expires_at: Number.MAX_SAFE_INTEGER,
token_type: 'Bearer',
base_url: 'https://api.githubcopilot.com',
});
});

test('rejects classic PATs locally', async () => {
const imported = await importGitHubCopilotLocalCredential({
resolveGitHubToken: async () => 'ghp_classic_pat',
});

assert.equal(imported.result.ok, false);
if (!imported.result.ok) {
assert.equal(imported.result.reason, 'token_exchange_failed');
assert.match(imported.result.message, /不支持 classic PAT/);
assert.equal(imported.result.message.includes('ghp_classic_pat'), false);
}
assert.equal(imported.secret, undefined);
});

test('rejects an unsupported local credential shape', async () => {
const imported = await importGitHubCopilotLocalCredential({
resolveGitHubToken: async () => 'unsupported-token',
});

assert.equal(imported.result.ok, false);
if (!imported.result.ok) assert.match(imported.result.message, /凭据类型不受支持/);
assert.equal(imported.secret, undefined);
});

test('reports when no local GitHub credential can be discovered', async () => {
const imported = await importGitHubCopilotLocalCredential({
resolveGitHubToken: async () => {
throw new Error('gh is not installed');
},
});

assert.equal(imported.result.ok, false);
if (!imported.result.ok) assert.match(imported.result.message, /未找到可导入/);
assert.equal(imported.secret, undefined);
});
});
Loading
Loading