@gajae-code/coding-agent 0.11.3 → 0.11.4
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 +24 -0
- package/dist/types/cli/worktree-cli.d.ts +8 -25
- package/dist/types/commands/gc.d.ts +4 -0
- package/dist/types/commands/worktree.d.ts +7 -32
- package/dist/types/gjc-runtime/gc-runtime.d.ts +9 -0
- package/dist/types/gjc-runtime/state-argv.d.ts +38 -0
- package/dist/types/modes/components/custom-editor.d.ts +8 -3
- package/dist/types/modes/components/tool-transcript-format.d.ts +19 -0
- package/dist/types/modes/controllers/input-controller.d.ts +8 -2
- package/dist/types/sdk/broker/broker.d.ts +1 -0
- package/dist/types/sdk/broker/discovery.d.ts +10 -0
- package/dist/types/sdk/broker/ensure.d.ts +24 -1
- package/dist/types/sdk/broker/internal.d.ts +3 -0
- package/dist/types/sdk/broker/session-index.d.ts +12 -0
- package/dist/types/sdk/broker/state-version.d.ts +2 -1
- package/dist/types/tools/ask.d.ts +39 -12
- package/dist/types/tools/browser/screenshot-format.d.ts +8 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +11 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +1 -1
- package/dist/types/tools/browser/tab-worker-path-resolver.d.ts +2 -0
- package/dist/types/tools/browser/tab-worker-smoke.d.ts +16 -0
- package/dist/types/tools/path-utils.d.ts +9 -14
- package/dist/types/tools/render-utils.d.ts +1 -8
- package/dist/types/tools/resource-gc.d.ts +14 -0
- package/dist/types/utils/image-loading.d.ts +23 -0
- package/dist/types/utils/image-resize.d.ts +2 -0
- package/dist/types/utils/pasted-image-loading.d.ts +39 -0
- package/dist/types/utils/pasted-image-path.d.ts +21 -19
- package/dist/types/web/scrapers/html-to-markdown.d.ts +5 -0
- package/dist/types/web/scrapers/types.d.ts +1 -5
- package/package.json +24 -8
- package/scripts/run-threat-model-check.ts +60 -0
- package/src/cli/worktree-cli.ts +9 -287
- package/src/cli.ts +10 -9
- package/src/commands/gc.ts +11 -1
- package/src/commands/sdk.ts +3 -2
- package/src/commands/worktree.ts +10 -53
- package/src/config/model-profiles.ts +15 -15
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/gjc-runtime/gc-render.ts +19 -1
- package/src/gjc-runtime/gc-runtime.ts +68 -3
- package/src/gjc-runtime/state-argv.ts +292 -0
- package/src/gjc-runtime/state-runtime.ts +42 -210
- package/src/modes/components/custom-editor.ts +103 -32
- package/src/modes/components/custom-provider-wizard.ts +26 -1
- package/src/modes/components/session-observer-overlay.ts +10 -23
- package/src/modes/components/tool-transcript-format.ts +72 -0
- package/src/modes/components/transcript-viewer-overlay.ts +42 -2
- package/src/modes/controllers/input-controller.ts +98 -37
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +13 -2
- package/src/sdk/broker/broker.ts +139 -32
- package/src/sdk/broker/discovery.ts +125 -0
- package/src/sdk/broker/ensure.ts +103 -19
- package/src/sdk/broker/internal.ts +10 -0
- package/src/sdk/broker/session-index.ts +228 -15
- package/src/sdk/broker/state-version.ts +5 -2
- package/src/sdk/bus/telegram-daemon.ts +50 -10
- package/src/session/internal/managed-session-scope.ts +15 -1
- package/src/tools/ask.ts +216 -41
- package/src/tools/bash-allowed-prefixes.ts +79 -29
- package/src/tools/browser/launch.ts +3 -1
- package/src/tools/browser/readable.ts +1 -1
- package/src/tools/browser/screenshot-format.ts +34 -0
- package/src/tools/browser/tab-protocol.ts +3 -0
- package/src/tools/browser/tab-supervisor.ts +125 -122
- package/src/tools/browser/tab-worker-entry.ts +33 -14
- package/src/tools/browser/tab-worker-path-resolver.ts +67 -0
- package/src/tools/browser/tab-worker-smoke.ts +87 -0
- package/src/tools/browser/tab-worker.ts +7 -5
- package/src/tools/path-utils.ts +42 -35
- package/src/tools/read.ts +7 -1
- package/src/tools/render-utils.ts +1 -27
- package/src/tools/resource-gc.ts +123 -34
- package/src/utils/image-loading.ts +85 -34
- package/src/utils/image-resize.ts +16 -9
- package/src/utils/pasted-image-loading.ts +514 -0
- package/src/utils/pasted-image-path.ts +223 -98
- package/src/web/scrapers/html-to-markdown.ts +68 -0
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/types.ts +1 -68
- package/src/web/search/providers/openai-compatible.ts +76 -23
|
@@ -5,16 +5,68 @@ import { SearchProvider } from "./base";
|
|
|
5
5
|
import { extractTextSources } from "./text-citations";
|
|
6
6
|
import { classifyProviderHttpError, withHardTimeout } from "./utils";
|
|
7
7
|
|
|
8
|
+
type JsonObject = Record<string, unknown>;
|
|
9
|
+
|
|
10
|
+
function isJsonObject(value: unknown): value is JsonObject {
|
|
11
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function malformedResponse(detail: string): never {
|
|
15
|
+
throw new SearchProviderError(
|
|
16
|
+
"openai-compatible",
|
|
17
|
+
`OpenAI-compatible web search returned malformed response body (${detail})`,
|
|
18
|
+
502,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function optionalArray(value: unknown, detail: string): unknown[] {
|
|
23
|
+
if (value === undefined) return [];
|
|
24
|
+
if (!Array.isArray(value)) malformedResponse(detail);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeResponseBody(value: unknown): JsonObject {
|
|
29
|
+
if (!isJsonObject(value)) malformedResponse("expected a JSON object");
|
|
30
|
+
|
|
31
|
+
const output = optionalArray(value.output, "output must be an array");
|
|
32
|
+
const choices = optionalArray(value.choices, "choices must be an array");
|
|
33
|
+
|
|
34
|
+
for (const item of output) {
|
|
35
|
+
if (!isJsonObject(item)) continue;
|
|
36
|
+
for (const content of optionalArray(item.content, "output content must be an array")) {
|
|
37
|
+
if (isJsonObject(content)) optionalArray(content.annotations, "output annotations must be an array");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const choice of choices) {
|
|
41
|
+
if (!isJsonObject(choice) || !isJsonObject(choice.message)) continue;
|
|
42
|
+
optionalArray(choice.message.annotations, "choice annotations must be an array");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { ...value, output, choices };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseResponseBody(text: string): JsonObject {
|
|
49
|
+
let value: unknown;
|
|
50
|
+
try {
|
|
51
|
+
value = text ? JSON.parse(text) : {};
|
|
52
|
+
} catch {
|
|
53
|
+
throw new SearchProviderError("openai-compatible", "OpenAI-compatible web search returned invalid JSON", 502);
|
|
54
|
+
}
|
|
55
|
+
return normalizeResponseBody(value);
|
|
56
|
+
}
|
|
57
|
+
|
|
8
58
|
/**
|
|
9
59
|
* Whether the response carries independent proof that a web search ran. Used to
|
|
10
60
|
* gate inline-citation recovery so a stray prose URL in a non-search answer is
|
|
11
61
|
* never promoted to a citation.
|
|
12
62
|
*/
|
|
13
|
-
function webSearchPerformed(json:
|
|
14
|
-
if (Array.isArray(json
|
|
63
|
+
function webSearchPerformed(json: JsonObject): boolean {
|
|
64
|
+
if (Array.isArray(json.output) && json.output.some(item => isJsonObject(item) && item.type === "web_search_call")) {
|
|
15
65
|
return true;
|
|
16
66
|
}
|
|
17
|
-
const
|
|
67
|
+
const toolUsage = isJsonObject(json.tool_usage) ? json.tool_usage : undefined;
|
|
68
|
+
const webSearch = toolUsage && isJsonObject(toolUsage.web_search) ? toolUsage.web_search : undefined;
|
|
69
|
+
const numRequests = webSearch?.num_requests;
|
|
18
70
|
return typeof numRequests === "number" && numRequests > 0;
|
|
19
71
|
}
|
|
20
72
|
|
|
@@ -23,16 +75,18 @@ function endpoint(baseUrl: string, api: string): string {
|
|
|
23
75
|
return api === "openai-completions" ? `${base}/chat/completions` : `${base}/responses`;
|
|
24
76
|
}
|
|
25
77
|
|
|
26
|
-
function textFromResponse(json:
|
|
78
|
+
function textFromResponse(json: JsonObject): string | undefined {
|
|
27
79
|
if (typeof json.output_text === "string") return json.output_text;
|
|
28
80
|
const chunks: string[] = [];
|
|
29
|
-
for (const item of json.output
|
|
30
|
-
|
|
31
|
-
|
|
81
|
+
for (const item of optionalArray(json.output, "output must be an array")) {
|
|
82
|
+
if (!isJsonObject(item)) continue;
|
|
83
|
+
for (const content of optionalArray(item.content, "output content must be an array")) {
|
|
84
|
+
if (isJsonObject(content) && typeof content.text === "string") chunks.push(content.text);
|
|
32
85
|
}
|
|
33
86
|
}
|
|
34
|
-
const
|
|
35
|
-
|
|
87
|
+
const firstChoice = optionalArray(json.choices, "choices must be an array")[0];
|
|
88
|
+
const message = isJsonObject(firstChoice) && isJsonObject(firstChoice.message) ? firstChoice.message : undefined;
|
|
89
|
+
if (typeof message?.content === "string") chunks.push(message.content);
|
|
36
90
|
return chunks.join("\n") || undefined;
|
|
37
91
|
}
|
|
38
92
|
|
|
@@ -55,24 +109,23 @@ function pushCitation(out: SearchCitation[], rawUrl: unknown, rawTitle: unknown,
|
|
|
55
109
|
function collectCitationAnnotations(annotations: unknown, out: SearchCitation[]): void {
|
|
56
110
|
if (!Array.isArray(annotations)) return;
|
|
57
111
|
for (const annotation of annotations) {
|
|
58
|
-
if (!annotation ||
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
const cite =
|
|
62
|
-
ann.url_citation && typeof ann.url_citation === "object" ? (ann.url_citation as Record<string, any>) : ann;
|
|
63
|
-
pushCitation(out, cite.url ?? cite.uri, cite.title, cite.text ?? cite.quote ?? ann.text);
|
|
112
|
+
if (!isJsonObject(annotation) || annotation.type !== "url_citation") continue;
|
|
113
|
+
const cite = isJsonObject(annotation.url_citation) ? annotation.url_citation : annotation;
|
|
114
|
+
pushCitation(out, cite.url ?? cite.uri, cite.title, cite.text ?? cite.quote ?? annotation.text);
|
|
64
115
|
}
|
|
65
116
|
}
|
|
66
117
|
|
|
67
|
-
function parseCitations(json:
|
|
118
|
+
function parseCitations(json: JsonObject): SearchCitation[] {
|
|
68
119
|
const citations: SearchCitation[] = [];
|
|
69
|
-
for (const item of json
|
|
70
|
-
|
|
71
|
-
|
|
120
|
+
for (const item of optionalArray(json.output, "output must be an array")) {
|
|
121
|
+
if (!isJsonObject(item)) continue;
|
|
122
|
+
for (const content of optionalArray(item.content, "output content must be an array")) {
|
|
123
|
+
if (isJsonObject(content)) collectCitationAnnotations(content.annotations, citations);
|
|
72
124
|
}
|
|
73
125
|
}
|
|
74
|
-
for (const choice of json
|
|
75
|
-
|
|
126
|
+
for (const choice of optionalArray(json.choices, "choices must be an array")) {
|
|
127
|
+
const message = isJsonObject(choice) && isJsonObject(choice.message) ? choice.message : undefined;
|
|
128
|
+
if (message) collectCitationAnnotations(message.annotations, citations);
|
|
76
129
|
}
|
|
77
130
|
const seen = new Set<string>();
|
|
78
131
|
return citations.filter(c => {
|
|
@@ -156,7 +209,7 @@ export class OpenAICompatibleSearchProvider extends SearchProvider {
|
|
|
156
209
|
response.status,
|
|
157
210
|
);
|
|
158
211
|
}
|
|
159
|
-
const json =
|
|
212
|
+
const json = parseResponseBody(text);
|
|
160
213
|
const citations = parseCitations(json);
|
|
161
214
|
const answer = textFromResponse(json);
|
|
162
215
|
const limit = params.limit ?? params.numSearchResults ?? 10;
|
|
@@ -178,7 +231,7 @@ export class OpenAICompatibleSearchProvider extends SearchProvider {
|
|
|
178
231
|
sources,
|
|
179
232
|
citations: citations.length > 0 ? citations : undefined,
|
|
180
233
|
model,
|
|
181
|
-
requestId: json.id,
|
|
234
|
+
requestId: typeof json.id === "string" ? json.id : undefined,
|
|
182
235
|
authMode: "api-key",
|
|
183
236
|
};
|
|
184
237
|
}
|