feat: integrate @anthropic-ai/claude-agent-sdk for latest version

- Added @anthropic-ai/claude-agent-sdk as a dependency for improved functionality.
- Updated controllablePromise to include a status property, allowing tracking of promise states (pending, resolved, rejected).
- Adjusted query function to utilize the new agent SDK for enhanced query capabilities.
- Updated i18n message files for better formatting and consistency.
This commit is contained in:
d-kimsuon
2025-10-20 01:03:13 +09:00
parent d55d52f659
commit 81a5d31f6e
8 changed files with 113 additions and 32 deletions

View File

@@ -14,7 +14,8 @@
"!src/lib/$path.ts",
"!**/*.css",
"!dist",
"!playwright.config.ts"
"!playwright.config.ts",
"!src/lib/i18n/locales/*/messages.ts"
]
},
"formatter": {

View File

@@ -42,6 +42,7 @@
"lingui:compile": "lingui compile --typescript"
},
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.22",
"@anthropic-ai/claude-code": "^2.0.22",
"@effect/platform": "^0.92.1",
"@effect/platform-node": "^0.98.4",

20
pnpm-lock.yaml generated
View File

@@ -8,6 +8,9 @@ importers:
.:
dependencies:
'@anthropic-ai/claude-agent-sdk':
specifier: ^0.1.22
version: 0.1.22(zod@4.1.12)
'@anthropic-ai/claude-code':
specifier: ^2.0.22
version: 2.0.22
@@ -187,6 +190,12 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
'@anthropic-ai/claude-agent-sdk@0.1.22':
resolution: {integrity: sha512-lDwbcwh5goRVUHRRqvX9v6Vj38VME1L+QIaLWzdqbK3Lwkkz9PVLNQFRDEyUOSNd9Fm4cAlfQZ0RCVe8tuo9TA==}
engines: {node: '>=18.0.0'}
peerDependencies:
zod: ^3.24.1
'@anthropic-ai/claude-code@2.0.22':
resolution: {integrity: sha512-3FVySgr2zYrHnQ0deOeCzXdLSa/JkCBm1QR7x4j07puNnvHrFhBo6whv/IMOcSvxL62RRW3csRcGsQhUGPNc/w==}
engines: {node: '>=18.0.0'}
@@ -4327,6 +4336,17 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
'@anthropic-ai/claude-agent-sdk@0.1.22(zod@4.1.12)':
dependencies:
zod: 4.1.12
optionalDependencies:
'@img/sharp-darwin-arm64': 0.33.5
'@img/sharp-darwin-x64': 0.33.5
'@img/sharp-linux-arm': 0.33.5
'@img/sharp-linux-arm64': 0.33.5
'@img/sharp-linux-x64': 0.33.5
'@img/sharp-win32-x64': 0.33.5
'@anthropic-ai/claude-code@2.0.22':
optionalDependencies:
'@img/sharp-darwin-arm64': 0.33.5

View File

@@ -1,25 +1,36 @@
export type ControllablePromise<T> = {
readonly promise: Promise<T>;
readonly resolve: (value: T) => void;
readonly reject: (reason?: unknown) => void;
promise: Promise<T>;
resolve: (value: T) => void;
reject: (reason?: unknown) => void;
status: "pending" | "resolved" | "rejected";
};
export const controllablePromise = <T>(): ControllablePromise<T> => {
let promiseResolve: ((value: T) => void) | undefined;
let promiseReject: ((reason?: unknown) => void) | undefined;
const promiseRef = {
status: "pending",
} as ControllablePromise<T>;
const promise = new Promise<T>((resolve, reject) => {
promiseResolve = resolve;
promiseReject = reject;
promiseResolve = (value) => {
promiseRef.status = "resolved";
resolve(value);
};
promiseReject = (reason) => {
promiseRef.status = "rejected";
reject(reason);
};
});
if (!promiseResolve || !promiseReject) {
throw new Error("Illegal state: Promise not created");
}
return {
promise,
resolve: promiseResolve,
reject: promiseReject,
} as const;
promiseRef.promise = promise;
promiseRef.resolve = promiseResolve;
promiseRef.reject = promiseReject;
return promiseRef;
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +1,24 @@
import { query as originalQuery } from "@anthropic-ai/claude-code";
import { query as agentSdkQuery } from "@anthropic-ai/claude-agent-sdk";
import { query as claudeCodeQuery } from "@anthropic-ai/claude-code";
import { Command, Path } from "@effect/platform";
import { Effect } from "effect";
import { EnvService } from "../../platform/services/EnvService";
import * as ClaudeCodeVersion from "./ClaudeCodeVersion";
type CCQuery = typeof originalQuery;
type CCQuery = typeof claudeCodeQuery;
type CCQueryPrompt = Parameters<CCQuery>[0]["prompt"];
type CCQueryOptions = NonNullable<Parameters<CCQuery>[0]["options"]>;
type AgentSdkQuery = typeof agentSdkQuery;
type AgentSdkQueryOptions = NonNullable<
Parameters<AgentSdkQuery>[0]["options"]
>;
type SharedOptions = Pick<
CCQueryOptions,
Extract<keyof AgentSdkQueryOptions, keyof CCQueryOptions>
>;
export const Config = Effect.gen(function* () {
const path = yield* Path.Path;
const envService = yield* EnvService;
@@ -73,26 +84,47 @@ export const getAvailableFeatures = (
patch: 86,
})
: false,
agentSdk:
claudeCodeVersion !== null
? ClaudeCodeVersion.greaterThanOrEqual(claudeCodeVersion, {
major: 1,
minor: 0,
patch: 125, // ClaudeCodeAgentSDK is available since v1.0.125
})
: false,
});
export const query = (prompt: CCQueryPrompt, options: CCQueryOptions) => {
export const query = (prompt: CCQueryPrompt, options: SharedOptions) => {
const { canUseTool, permissionMode, ...baseOptions } = options;
return Effect.gen(function* () {
const { claudeCodeExecutablePath, claudeCodeVersion } = yield* Config;
const availableFeatures = getAvailableFeatures(claudeCodeVersion);
return originalQuery({
const options: SharedOptions = {
pathToClaudeCodeExecutable: claudeCodeExecutablePath,
...baseOptions,
...(availableFeatures.canUseTool
? { canUseTool, permissionMode }
: {
permissionMode: "bypassPermissions",
}),
};
if (availableFeatures.agentSdk) {
return agentSdkQuery({
prompt,
options: {
systemPrompt: { type: "preset", preset: "claude_code" },
settingSources: ["user", "project", "local"],
...options,
},
});
}
return claudeCodeQuery({
prompt,
options: {
pathToClaudeCodeExecutable: claudeCodeExecutablePath,
...baseOptions,
...(availableFeatures.canUseTool
? { canUseTool, permissionMode }
: {
permissionMode: "bypassPermissions",
}),
},
options: options,
});
});
};

View File

@@ -293,6 +293,14 @@ const LayerImpl = Effect.gen(function* () {
}),
);
if (sessionInitializedPromise.status === "pending") {
sessionInitializedPromise.reject(error);
}
if (sessionFileCreatedPromise.status === "pending") {
sessionFileCreatedPromise.reject(error);
}
return "continue" as const;
});
@@ -302,6 +310,14 @@ const LayerImpl = Effect.gen(function* () {
}
}
} catch (error) {
if (sessionInitializedPromise.status === "pending") {
sessionInitializedPromise.reject(error);
}
if (sessionFileCreatedPromise.status === "pending") {
sessionFileCreatedPromise.reject(error);
}
await Effect.runPromise(
sessionProcessService.changeTaskState({
sessionProcessId: sessionProcess.def.sessionProcessId,
@@ -319,6 +335,12 @@ const LayerImpl = Effect.gen(function* () {
const daemonPromise = handleSessionProcessDaemon()
.catch((error) => {
console.error("Error occur in task daemon process", error);
if (sessionInitializedPromise.status === "pending") {
sessionInitializedPromise.reject(error);
}
if (sessionFileCreatedPromise.status === "pending") {
sessionFileCreatedPromise.reject(error);
}
throw error;
})
.finally(() => {