@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
81 lines • 2.78 kB
JavaScript
/**
* User-level storage for GitHub Copilot credentials.
* The stored token is the GitHub OAuth access token from the device flow
* (used to obtain short-lived Copilot API tokens). Stored under config path
* (e.g. ~/.config/nanocoder/) so they are not in project config.
*/
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from 'fs';
import { join } from 'path';
import { clearCopilotTokenCache } from '../auth/github-copilot.js';
import { getConfigPath } from '../config/paths.js';
const FILENAME = 'copilot-credentials.json';
/** Shared message when no Copilot credential is found (used by provider-factory and client-factory). */
export function getCopilotNoCredentialsMessage(providerName) {
return `No Copilot credentials for "${providerName}". Type /copilot-login in the chat to log in, or run: nanocoder copilot login (from project: node dist/cli.js copilot login)`;
}
function getCredentialsPath() {
return join(getConfigPath(), FILENAME);
}
function loadStore() {
const path = getCredentialsPath();
if (!existsSync(path)) {
return {};
}
try {
const raw = readFileSync(path, 'utf-8');
const data = JSON.parse(raw);
if (data !== null && typeof data === 'object' && !Array.isArray(data)) {
return data;
}
}
catch {
// Invalid or unreadable
}
return {};
}
function writeStore(store) {
const dir = getConfigPath();
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
const filePath = getCredentialsPath();
writeFileSync(filePath, JSON.stringify(store, null, 2), {
encoding: 'utf-8',
mode: 0o600,
});
chmodSync(filePath, 0o600);
}
/**
* Get stored Copilot credential for a provider name (e.g. "GitHub Copilot").
*/
export function loadCopilotCredential(providerName) {
const store = loadStore();
const entry = store[providerName];
if (!entry || typeof entry.oauthToken !== 'string') {
return null;
}
return {
oauthToken: entry.oauthToken,
enterpriseUrl: typeof entry.enterpriseUrl === 'string' ? entry.enterpriseUrl : undefined,
};
}
/**
* Save GitHub OAuth token (from device flow) for a provider name.
*/
export function saveCopilotCredential(providerName, oauthToken, enterpriseUrl) {
const store = loadStore();
store[providerName] = { oauthToken, enterpriseUrl };
writeStore(store);
}
/**
* Remove stored credential for a provider name.
*/
export function removeCopilotCredential(providerName) {
const store = loadStore();
if (providerName in store) {
delete store[providerName];
writeStore(store);
clearCopilotTokenCache();
}
}
//# sourceMappingURL=copilot-credentials.js.map