@gajae-code/coding-agent 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -1
- package/dist/types/config/model-registry.d.ts +8 -0
- package/dist/types/config/model-resolver.d.ts +4 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +26 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +44 -0
- package/dist/types/goals/tools/goal-tool.d.ts +4 -4
- package/dist/types/hooks/skill-state.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +5 -7
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/sdk.d.ts +2 -4
- package/dist/types/session/agent-session.d.ts +3 -9
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +28 -0
- package/package.json +13 -9
- package/src/config/model-registry.ts +45 -0
- package/src/config/model-resolver.ts +5 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +30 -30
- package/src/defaults/gjc/skills/team/SKILL.md +1 -0
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +51 -21
- package/src/gjc-runtime/team-runtime.ts +80 -1
- package/src/gjc-runtime/ultragoal-guard.ts +239 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +318 -4
- package/src/goals/tools/goal-tool.ts +10 -4
- package/src/hooks/native-skill-hook.ts +26 -0
- package/src/hooks/skill-state.ts +59 -0
- package/src/main.ts +2 -17
- package/src/modes/components/model-selector.ts +225 -33
- package/src/modes/controllers/selector-controller.ts +16 -3
- package/src/modes/interactive-mode.ts +34 -22
- package/src/modes/prompt-action-autocomplete.ts +40 -15
- package/src/sdk.ts +3 -1
- package/src/session/agent-session.ts +40 -4
- package/src/setup/model-onboarding-guidance.ts +5 -3
- package/src/skill-state/deep-interview-mutation-guard.ts +303 -0
- package/src/slash-commands/builtin-registry.ts +130 -11
- package/src/tools/ask.ts +55 -17
- package/src/tools/ast-edit.ts +7 -0
- package/src/tools/bash.ts +2 -1
- package/src/tools/gh.ts +37 -9
- package/src/tools/image-gen.ts +19 -10
- package/src/tools/path-utils.ts +1 -0
package/src/tools/gh.ts
CHANGED
|
@@ -106,6 +106,34 @@ const GH_PR_CHECKOUT_FIELDS = [
|
|
|
106
106
|
"title",
|
|
107
107
|
"url",
|
|
108
108
|
];
|
|
109
|
+
|
|
110
|
+
const PR_CHECKOUT_BRANCH_CONFIG = {
|
|
111
|
+
headRef: "gjcPrHeadRef",
|
|
112
|
+
url: "gjcPrUrl",
|
|
113
|
+
isCrossRepository: "gjcPrIsCrossRepository",
|
|
114
|
+
maintainerCanModify: "gjcPrMaintainerCanModify",
|
|
115
|
+
} as const;
|
|
116
|
+
|
|
117
|
+
const LEGACY_PR_CHECKOUT_BRANCH_CONFIG = {
|
|
118
|
+
headRef: "ompPrHeadRef",
|
|
119
|
+
url: "ompPrUrl",
|
|
120
|
+
isCrossRepository: "ompPrIsCrossRepository",
|
|
121
|
+
maintainerCanModify: "ompPrMaintainerCanModify",
|
|
122
|
+
} as const;
|
|
123
|
+
|
|
124
|
+
type PrCheckoutBranchConfigKey = keyof typeof PR_CHECKOUT_BRANCH_CONFIG;
|
|
125
|
+
|
|
126
|
+
async function getPrCheckoutBranchConfig(
|
|
127
|
+
repoRoot: string,
|
|
128
|
+
localBranch: string,
|
|
129
|
+
key: PrCheckoutBranchConfigKey,
|
|
130
|
+
signal?: AbortSignal,
|
|
131
|
+
): Promise<string | undefined> {
|
|
132
|
+
return (
|
|
133
|
+
(await git.config.getBranch(repoRoot, localBranch, PR_CHECKOUT_BRANCH_CONFIG[key], signal)) ??
|
|
134
|
+
(await git.config.getBranch(repoRoot, localBranch, LEGACY_PR_CHECKOUT_BRANCH_CONFIG[key], signal))
|
|
135
|
+
);
|
|
136
|
+
}
|
|
109
137
|
// /search/<endpoint> API response shapes (subset). Used when projecting raw
|
|
110
138
|
// REST results into the normalized `GhSearch*Result` shapes the formatters
|
|
111
139
|
// consume. We talk to the API directly because `gh search prs`/`issues`
|
|
@@ -1023,21 +1051,21 @@ async function resolvePrBranchPushTarget(
|
|
|
1023
1051
|
maintainerCanModify?: boolean;
|
|
1024
1052
|
isCrossRepository: boolean;
|
|
1025
1053
|
}> {
|
|
1026
|
-
const headRef = await
|
|
1054
|
+
const headRef = await getPrCheckoutBranchConfig(repoRoot, localBranch, "headRef", signal);
|
|
1027
1055
|
if (!headRef) {
|
|
1028
1056
|
throw new ToolError(`branch ${localBranch} has no PR push metadata; check it out via op: pr_checkout first`);
|
|
1029
1057
|
}
|
|
1030
1058
|
|
|
1031
1059
|
const pushRemote = await git.config.getBranch(repoRoot, localBranch, "pushRemote", signal);
|
|
1032
1060
|
const remote = await git.config.getBranch(repoRoot, localBranch, "remote", signal);
|
|
1033
|
-
const prUrl = await
|
|
1034
|
-
const maintainerCanModifyValue = await
|
|
1061
|
+
const prUrl = await getPrCheckoutBranchConfig(repoRoot, localBranch, "url", signal);
|
|
1062
|
+
const maintainerCanModifyValue = await getPrCheckoutBranchConfig(
|
|
1035
1063
|
repoRoot,
|
|
1036
1064
|
localBranch,
|
|
1037
|
-
"
|
|
1065
|
+
"maintainerCanModify",
|
|
1038
1066
|
signal,
|
|
1039
1067
|
);
|
|
1040
|
-
const isCrossRepositoryValue = await
|
|
1068
|
+
const isCrossRepositoryValue = await getPrCheckoutBranchConfig(repoRoot, localBranch, "isCrossRepository", signal);
|
|
1041
1069
|
|
|
1042
1070
|
const remoteName = pushRemote ?? remote;
|
|
1043
1071
|
if (!remoteName) {
|
|
@@ -2989,19 +3017,19 @@ async function checkoutPullRequest(
|
|
|
2989
3017
|
await git.config.setBranch(repoRoot, localBranch, "remote", remote.name, signal);
|
|
2990
3018
|
await git.config.setBranch(repoRoot, localBranch, "merge", `refs/heads/${headRefName}`, signal);
|
|
2991
3019
|
await git.config.setBranch(repoRoot, localBranch, "pushRemote", remote.name, signal);
|
|
2992
|
-
await git.config.setBranch(repoRoot, localBranch,
|
|
2993
|
-
await git.config.setBranch(repoRoot, localBranch,
|
|
3020
|
+
await git.config.setBranch(repoRoot, localBranch, PR_CHECKOUT_BRANCH_CONFIG.headRef, headRefName, signal);
|
|
3021
|
+
await git.config.setBranch(repoRoot, localBranch, PR_CHECKOUT_BRANCH_CONFIG.url, data.url ?? "", signal);
|
|
2994
3022
|
await git.config.setBranch(
|
|
2995
3023
|
repoRoot,
|
|
2996
3024
|
localBranch,
|
|
2997
|
-
|
|
3025
|
+
PR_CHECKOUT_BRANCH_CONFIG.isCrossRepository,
|
|
2998
3026
|
String(Boolean(data.isCrossRepository)),
|
|
2999
3027
|
signal,
|
|
3000
3028
|
);
|
|
3001
3029
|
await git.config.setBranch(
|
|
3002
3030
|
repoRoot,
|
|
3003
3031
|
localBranch,
|
|
3004
|
-
|
|
3032
|
+
PR_CHECKOUT_BRANCH_CONFIG.maintainerCanModify,
|
|
3005
3033
|
String(Boolean(data.maintainerCanModify)),
|
|
3006
3034
|
signal,
|
|
3007
3035
|
);
|
package/src/tools/image-gen.ts
CHANGED
|
@@ -44,6 +44,7 @@ interface ImageApiKey {
|
|
|
44
44
|
apiKey: string;
|
|
45
45
|
projectId?: string;
|
|
46
46
|
model?: Model;
|
|
47
|
+
authCredentialType?: "api_key" | "oauth";
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
const responseModalitySchema = z.enum(["IMAGE", "TEXT"] as const);
|
|
@@ -441,6 +442,7 @@ async function findOpenAIHostedImageCredentials(
|
|
|
441
442
|
provider: getOpenAIHostedImageProvider(activeModel),
|
|
442
443
|
apiKey,
|
|
443
444
|
model: activeModel,
|
|
445
|
+
authCredentialType: modelRegistry.getSessionCredentialType?.(activeModel.provider, sessionId),
|
|
444
446
|
};
|
|
445
447
|
}
|
|
446
448
|
|
|
@@ -700,16 +702,21 @@ function getOpenAIResponseErrorMessage(rawText: string): string {
|
|
|
700
702
|
}
|
|
701
703
|
}
|
|
702
704
|
|
|
703
|
-
function getOpenAIBaseUrl(model: Model): string {
|
|
704
|
-
|
|
705
|
-
model.
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
705
|
+
function getOpenAIBaseUrl(model: Model, authCredentialType?: "api_key" | "oauth"): string {
|
|
706
|
+
if (model.api === "openai-codex-responses" || model.provider === "openai-codex") {
|
|
707
|
+
return (model.baseUrl || CODEX_BASE_URL).replace(/\/+$/, "");
|
|
708
|
+
}
|
|
709
|
+
if (authCredentialType === "oauth") return DEFAULT_OPENAI_BASE_URL;
|
|
710
|
+
const envBaseUrl = $env.OPENAI_BASE_URL?.trim();
|
|
711
|
+
const configuredBaseUrl = model.baseUrl?.trim();
|
|
712
|
+
if (envBaseUrl && (!configuredBaseUrl || configuredBaseUrl.toLowerCase().includes("api.openai.com"))) {
|
|
713
|
+
return envBaseUrl.replace(/\/+$/, "");
|
|
714
|
+
}
|
|
715
|
+
return (configuredBaseUrl || envBaseUrl || DEFAULT_OPENAI_BASE_URL).replace(/\/+$/, "");
|
|
709
716
|
}
|
|
710
717
|
|
|
711
|
-
function getOpenAIResponsesUrl(model: Model): string {
|
|
712
|
-
const baseUrl = getOpenAIBaseUrl(model);
|
|
718
|
+
function getOpenAIResponsesUrl(model: Model, authCredentialType?: "api_key" | "oauth"): string {
|
|
719
|
+
const baseUrl = getOpenAIBaseUrl(model, authCredentialType);
|
|
713
720
|
if (model.api !== "openai-codex-responses" && model.provider !== "openai-codex") {
|
|
714
721
|
return `${baseUrl}/responses`;
|
|
715
722
|
}
|
|
@@ -782,11 +789,12 @@ async function generateOpenAIHostedImage(
|
|
|
782
789
|
inputImages: InlineImageData[],
|
|
783
790
|
signal: AbortSignal | undefined,
|
|
784
791
|
sessionId: string | undefined,
|
|
792
|
+
options?: { authCredentialType?: "api_key" | "oauth" },
|
|
785
793
|
): Promise<OpenAIHostedImageResult> {
|
|
786
794
|
const promptText = assemblePrompt(params);
|
|
787
795
|
const stream = model.api === "openai-codex-responses" || model.provider === "openai-codex";
|
|
788
796
|
const requestBody = buildOpenAIHostedImageRequest(model, promptText, params, inputImages, stream);
|
|
789
|
-
const response = await fetch(getOpenAIResponsesUrl(model), {
|
|
797
|
+
const response = await fetch(getOpenAIResponsesUrl(model, options?.authCredentialType), {
|
|
790
798
|
method: "POST",
|
|
791
799
|
headers: buildOpenAIImageHeaders(model, apiKey, sessionId),
|
|
792
800
|
body: JSON.stringify(requestBody),
|
|
@@ -946,6 +954,7 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
|
|
|
946
954
|
resolvedImages,
|
|
947
955
|
requestSignal,
|
|
948
956
|
sessionId,
|
|
957
|
+
{ authCredentialType: apiKey.authCredentialType },
|
|
949
958
|
);
|
|
950
959
|
|
|
951
960
|
if (parsed.images.length === 0) {
|
|
@@ -1075,7 +1084,7 @@ export const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails
|
|
|
1075
1084
|
headers: {
|
|
1076
1085
|
"Content-Type": "application/json",
|
|
1077
1086
|
Authorization: `Bearer ${apiKey.apiKey}`,
|
|
1078
|
-
"HTTP-Referer": "https://gajae
|
|
1087
|
+
"HTTP-Referer": "https://gaebal-gajae.dev/",
|
|
1079
1088
|
"X-OpenRouter-Title": "Gajae Code",
|
|
1080
1089
|
"X-OpenRouter-Categories": "cli-agent",
|
|
1081
1090
|
},
|
package/src/tools/path-utils.ts
CHANGED