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: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,9 @@ jobs:

- name: Verify
run: npm run verify

- name: Verify standalone website
run: |
npm ci --prefix website
npm test --prefix website
npm run build --prefix website
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,5 @@ tasks/
gajae-app-source.tar.gz
gajae-app-sidebar.html
electron/*.tar.gz
# Marketing website build output
/website/dist/
4 changes: 4 additions & 0 deletions scripts/check-identity.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const MAX_FILE_BYTES = 64 * 1024 * 1024;
const MAX_ARCHIVE_BYTES = 512 * 1024 * 1024;
const MAX_REPORTED_ERRORS = 100;
const GENERATED_DIRECTORIES = ['dist', 'dist-server', 'release'];
const SKIPPED_RELATIVE_DIRECTORIES = new Set(['website/dist']);
const SKIPPED_DIRECTORIES = new Set([
'.codegraph',
'.desktop-build',
Expand Down Expand Up @@ -258,6 +259,9 @@ async function walkDirectory(directoryPath, category) {
if (category === 'source' && GENERATED_DIRECTORIES.includes(entry.name)) {
continue;
}
if (SKIPPED_RELATIVE_DIRECTORIES.has(relativePath)) {
continue;
}

scanPath(relativePath);
await walkDirectory(absolutePath, category);
Expand Down
9 changes: 9 additions & 0 deletions server/gjc-bun-sdk-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type SdkRunConfig = {
credential: ExactCredentialRef;
modelId: string;
modelProfile?: string;
effort?: 'default' | 'inherit' | 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
toolNames: string[];
spawns: string;
bashPolicy: AppBashPolicy;
Expand Down Expand Up @@ -84,6 +85,9 @@ function configFromOptions(value: Record<string, unknown>): SdkRunConfig {
|| !exactCredentialRef(candidate.credential)
|| typeof candidate.modelId !== 'string' || !candidate.modelId
|| (candidate.modelProfile !== undefined && (typeof candidate.modelProfile !== 'string' || !candidate.modelProfile))
|| (candidate.effort !== undefined && ![
'default', 'inherit', 'off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max',
].includes(String(candidate.effort)))
|| !Array.isArray(candidate.toolNames) || candidate.toolNames.some((name) => typeof name !== 'string' || !name)
|| typeof candidate.spawns !== 'string'
|| !object(candidate.bashPolicy) || !Array.isArray(candidate.bashPolicy.allowedPrefixes)
Expand Down Expand Up @@ -305,6 +309,11 @@ export class GjcBunSdkAdapter implements GjcWorkerRuntime {
authStorage: this.authStorage,
modelRegistry: this.modelRegistry,
model,
...(
config.effort && config.effort !== 'default' && config.effort !== 'inherit'
? { thinkingLevel: config.effort }
: {}
),
providerSessionId: resumedId ?? sessionManager.getSessionId(),
...(resolvedCredential.credentialSelector
? { credentialSelector: resolvedCredential.credentialSelector }
Expand Down
14 changes: 14 additions & 0 deletions server/gjc-sdk-contract.bun.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,20 @@ test('resume opens the sole exact session file and never re-emits session.create
assert.equal(methods(f.frames).includes('session.created'), false);
} finally { await f.close(); }
});
test('session effort is passed to the SDK as the turn thinking level', async () => {
const f = await fixture();
try {
const run = f.host.handle(request('session.start', 'reasoning-effort', {
message: 'reason',
options: { ...f.options, effort: 'high' },
}));
const session = await firstSession(f.sessions);
await session.promptStarted.promise;
session.complete();
await run;
assert.equal(f.factoryOptions[0]!.thinkingLevel, 'high');
} finally { await f.close(); }
});
test('sequential runs clone global settings for each cwd while retaining the session root', async () => {
const f = await fixture();
const firstCwd = await mkdtemp(join(tmpdir(), 'gjc-cwd-one-'));
Expand Down
7 changes: 4 additions & 3 deletions server/gjc-worker-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ test('resume root resolution selects either allowlisted store from indexed sessi
await Promise.all([writeFile(paths.live, '{}\n'), writeFile(paths.saved, '{}\n')]);
const lookup = async (sessionId: string) => paths[sessionId as keyof typeof paths];

// The resolver returns the canonical (realpath) root; macOS resolves the
// temp store under /var to /private/var, so normalize expectations too.
// The resolver returns the directory SessionManager must scan. macOS
// resolves the temp store under /var to /private/var, so normalize
// expectations too.
assert.equal(await resolveGjcResumeSessionRoot('live', liveRoot, lookup), await realpath(liveRoot));
assert.equal(await resolveGjcResumeSessionRoot('saved', liveRoot, lookup), await realpath(savedRoot));
assert.equal(await resolveGjcResumeSessionRoot('saved', liveRoot, lookup), await realpath(savedDirectory));
} finally {
await Promise.all([
rm(tempDirectory, { recursive: true, force: true }),
Expand Down
7 changes: 6 additions & 1 deletion server/gjc-worker-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,18 @@ export async function resolveGjcResumeSessionRoot(
): Promise<string | undefined> {
try {
const sessionPath = await realpath(await lookup(sessionId) ?? '');
const sessionDirectory = dirname(sessionPath);
const roots = [
join(homedir(), '.gjc', 'agent', 'sessions'),
liveSessionRoot,
];
for (const root of roots) {
try {
const canonicalRoot = await realpath(root);
if (containedBy(canonicalRoot, sessionPath)) return canonicalRoot;
// SessionManager.list() scans only the supplied directory. Managed
// sessions live one level below the global sessions root, so returning
// that global root makes every historical resume look missing.
if (containedBy(canonicalRoot, sessionPath)) return sessionDirectory;
} catch {
// A missing or inaccessible allowlist root cannot contain a resumable session.
}
Expand Down Expand Up @@ -270,6 +274,7 @@ export async function enrichGjcSdkRunOptions(options: GjcWorkerOptions): Promise
credential: options.credential ?? { kind: 'stored' },
modelId,
...(modelProfile ? { modelProfile } : {}),
effort: typeof options.effort === 'string' && options.effort ? options.effort : 'default',
toolNames: options.toolNames ?? [...GJC_AGENT_TOOL_NAMES],
spawns: options.spawns ?? '*',
bashPolicy: options.bashPolicy ?? { allowedPrefixes: [] },
Expand Down
2 changes: 2 additions & 0 deletions server/modules/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { sessionSynchronizerService } from './services/session-synchronizer.service.js';

export { providerModelsService } from './services/provider-models.service.js';

export { initializeSessionsWatcher } from './services/sessions-watcher.service.js';
export { closeSessionsWatcher } from './services/sessions-watcher.service.js';
Loading