@gajae-code/coding-agent 0.9.1 → 0.9.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 +36 -0
- package/dist/types/capability/mcp.d.ts +3 -1
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/notify-cli.d.ts +5 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/mcp.d.ts +1 -1
- package/dist/types/config/model-profile-activation.d.ts +7 -7
- package/dist/types/config/model-registry.d.ts +7 -3
- package/dist/types/config/model-resolver.d.ts +2 -2
- package/dist/types/config/settings-schema.d.ts +1 -1
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +20 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +9 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -2
- package/dist/types/modes/components/status-line/types.d.ts +6 -0
- package/dist/types/modes/components/status-line.d.ts +1 -0
- package/dist/types/modes/components/thinking-selector.d.ts +6 -1
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +12 -0
- package/dist/types/notifications/config-commands.d.ts +29 -0
- package/dist/types/notifications/index.d.ts +12 -1
- package/dist/types/notifications/telegram-daemon-cli.d.ts +3 -3
- package/dist/types/notifications/threaded-render.d.ts +2 -0
- package/dist/types/notifications/topic-registry.d.ts +4 -5
- package/dist/types/runtime-credential-selector.d.ts +7 -0
- package/dist/types/runtime-mcp/config-writer.d.ts +4 -3
- package/dist/types/runtime-mcp/types.d.ts +5 -4
- package/dist/types/sdk.d.ts +7 -1
- package/dist/types/session/agent-session.d.ts +22 -3
- package/dist/types/session/session-manager.d.ts +1 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/skill-discovery.d.ts +40 -0
- package/dist/types/tools/skill.d.ts +9 -8
- package/dist/types/utils/linkedom.d.ts +4 -0
- package/dist/types/utils/pasted-image-path.d.ts +5 -3
- package/package.json +11 -7
- package/scripts/build-binary.ts +2 -40
- package/scripts/compile-args.ts +91 -0
- package/scripts/generate-docs-index.ts +1 -0
- package/src/capability/mcp.ts +3 -1
- package/src/cli/args.ts +8 -0
- package/src/cli/mcp-cli.ts +108 -26
- package/src/cli/notify-cli.ts +27 -1
- package/src/cli.ts +26 -0
- package/src/commands/launch.ts +5 -0
- package/src/commands/mcp.ts +8 -8
- package/src/commands/notify.ts +2 -2
- package/src/commands/stats.ts +6 -2
- package/src/config/mcp-schema.json +21 -17
- package/src/config/model-profile-activation.ts +23 -7
- package/src/config/model-registry.ts +21 -4
- package/src/config/model-resolver.ts +5 -16
- package/src/config/settings-schema.ts +3 -2
- package/src/config/settings.ts +24 -1
- package/src/coordinator-mcp/server.ts +7 -4
- package/src/discovery/builtin.ts +14 -0
- package/src/discovery/mcp-json.ts +14 -0
- package/src/extensibility/runtime-skill-discovery.ts +229 -0
- package/src/gjc-runtime/launch-tmux.ts +72 -12
- package/src/gjc-runtime/psmux-detect.ts +17 -2
- package/src/gjc-runtime/state-runtime.ts +105 -12
- package/src/gjc-runtime/team-runtime.ts +35 -3
- package/src/gjc-runtime/workflow-manifest.generated.json +4 -28
- package/src/gjc-runtime/workflow-manifest.ts +1 -7
- package/src/internal-urls/docs-index.generated.ts +3 -2
- package/src/internal-urls/gjc-protocol.ts +14 -1
- package/src/main.ts +26 -3
- package/src/modes/components/assistant-message.ts +1 -1
- package/src/modes/components/settings-selector.ts +3 -3
- package/src/modes/components/status-line/presets.ts +5 -7
- package/src/modes/components/status-line/segments.ts +14 -0
- package/src/modes/components/status-line/types.ts +6 -0
- package/src/modes/components/status-line.ts +7 -1
- package/src/modes/components/thinking-selector.ts +79 -18
- package/src/modes/components/tool-execution.ts +1 -1
- package/src/modes/controllers/event-controller.ts +9 -9
- package/src/modes/controllers/input-controller.ts +52 -11
- package/src/modes/controllers/selector-controller.ts +7 -5
- package/src/modes/interactive-mode.ts +12 -4
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +202 -47
- package/src/notifications/config-commands.ts +70 -0
- package/src/notifications/index.ts +156 -9
- package/src/notifications/rich-render.ts +1 -0
- package/src/notifications/telegram-daemon-cli.ts +13 -5
- package/src/notifications/telegram-daemon.ts +87 -4
- package/src/notifications/threaded-render.ts +14 -0
- package/src/notifications/topic-registry.ts +9 -8
- package/src/prompts/tools/skill-discovery.md +13 -0
- package/src/prompts/tools/skill.md +2 -2
- package/src/runtime-credential-selector.ts +35 -0
- package/src/runtime-mcp/config-writer.ts +4 -3
- package/src/runtime-mcp/config.ts +1 -0
- package/src/runtime-mcp/types.ts +5 -4
- package/src/sdk.ts +68 -5
- package/src/session/agent-session.ts +159 -21
- package/src/session/session-manager.ts +68 -40
- package/src/system-prompt.ts +4 -6
- package/src/tools/bash-interactive.ts +9 -4
- package/src/tools/browser/readable.ts +2 -2
- package/src/tools/fetch.ts +5 -5
- package/src/tools/index.ts +4 -0
- package/src/tools/skill-discovery.ts +73 -0
- package/src/tools/skill.ts +29 -13
- package/src/utils/linkedom.ts +14 -0
- package/src/utils/pasted-image-path.ts +23 -9
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/go-pkg.ts +2 -2
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +2 -2
- package/src/web/scrapers/twitter.ts +3 -2
- package/src/web/scrapers/wikipedia.ts +2 -2
- package/src/export/html/template.css +0 -1060
- package/src/export/html/template.html +0 -47
- package/src/export/html/template.js +0 -2314
- package/vendor/insane-search/engine/tests/test_hardening.py +0 -57
- package/vendor/insane-search/engine/tests/test_smoke.py +0 -152
- package/vendor/insane-search/engine/tests/test_u1.py +0 -200
- package/vendor/insane-search/engine/tests/test_u4.py +0 -131
- package/vendor/insane-search/engine/tests/test_u5.py +0 -163
- package/vendor/insane-search/engine/tests/test_u7.py +0 -124
- package/vendor/insane-search/engine/tests/test_u8.py +0 -216
|
@@ -156,6 +156,10 @@ export interface AsyncJobSnapshot {
|
|
|
156
156
|
recent: AsyncJobSnapshotItem[];
|
|
157
157
|
delivery: AsyncJobDeliveryState;
|
|
158
158
|
}
|
|
159
|
+
export interface RetainedMemorySample {
|
|
160
|
+
tuiChatChildren?: number;
|
|
161
|
+
tuiCachedRenderBytes?: number;
|
|
162
|
+
}
|
|
159
163
|
export interface AgentSessionConfig {
|
|
160
164
|
agent: Agent;
|
|
161
165
|
sessionManager: SessionManager;
|
|
@@ -237,6 +241,8 @@ export interface AgentSessionConfig {
|
|
|
237
241
|
* **MUST NOT** dispose it on their own teardown.
|
|
238
242
|
*/
|
|
239
243
|
ownedAsyncJobManager?: AsyncJobManager;
|
|
244
|
+
/** Cheap TUI retained-memory counters; absent for headless sessions. */
|
|
245
|
+
retainedMemorySampler?: () => RetainedMemorySample;
|
|
240
246
|
/**
|
|
241
247
|
* MCPManager whose lifecycle this session owns (top-level sessions that
|
|
242
248
|
* connected plugin-bundle MCP servers). Only the owned manager is
|
|
@@ -270,6 +276,8 @@ export interface PromptOptions {
|
|
|
270
276
|
images?: ImageContent[];
|
|
271
277
|
/** When streaming, how to queue the message: "steer" (interrupt) or "followUp" (wait). */
|
|
272
278
|
streamingBehavior?: "steer" | "followUp";
|
|
279
|
+
/** When set to "sequential", this follow-up is delivered one prompt at a time even if followUpMode is "all". */
|
|
280
|
+
followUpQueuePolicy?: "respect-mode" | "sequential";
|
|
273
281
|
/** Optional tool choice override for the next LLM call. */
|
|
274
282
|
toolChoice?: ToolChoice;
|
|
275
283
|
/** Send as developer/system message instead of user. Providers that support it use the developer role; others fall back to user. */
|
|
@@ -366,6 +374,15 @@ export declare const __agentSessionPerfCounters: {
|
|
|
366
374
|
reset(): void;
|
|
367
375
|
};
|
|
368
376
|
export declare function buildContextInjectionSignature(kind: string, parts: readonly string[]): string;
|
|
377
|
+
export declare class StreamingEditFileCache {
|
|
378
|
+
#private;
|
|
379
|
+
get(path: string): string | undefined;
|
|
380
|
+
set(path: string, content: string): void;
|
|
381
|
+
delete(path: string): void;
|
|
382
|
+
clear(): void;
|
|
383
|
+
has(path: string): boolean;
|
|
384
|
+
get totalBytes(): number;
|
|
385
|
+
}
|
|
369
386
|
export declare class AgentSession {
|
|
370
387
|
#private;
|
|
371
388
|
readonly agent: Agent;
|
|
@@ -657,7 +674,7 @@ export declare class AgentSession {
|
|
|
657
674
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
658
675
|
*/
|
|
659
676
|
prompt(text: string, options?: PromptOptions): Promise<void>;
|
|
660
|
-
promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice">): Promise<void>;
|
|
677
|
+
promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy">): Promise<void>;
|
|
661
678
|
/**
|
|
662
679
|
* Queue a steering message to interrupt the agent mid-run.
|
|
663
680
|
*/
|
|
@@ -665,7 +682,7 @@ export declare class AgentSession {
|
|
|
665
682
|
/**
|
|
666
683
|
* Queue a follow-up message to process after the agent would otherwise stop.
|
|
667
684
|
*/
|
|
668
|
-
followUp(text: string, images?: ImageContent[]): Promise<void>;
|
|
685
|
+
followUp(text: string, images?: ImageContent[], options?: Pick<PromptOptions, "followUpQueuePolicy">): Promise<void>;
|
|
669
686
|
queueDeferredMessage(message: CustomMessage): void;
|
|
670
687
|
queueDeferredMessageForTests(message: CustomMessage, triggerTurn?: boolean): void;
|
|
671
688
|
/**
|
|
@@ -679,6 +696,7 @@ export declare class AgentSession {
|
|
|
679
696
|
sendCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: {
|
|
680
697
|
triggerTurn?: boolean;
|
|
681
698
|
deliverAs?: "steer" | "followUp" | "nextTurn";
|
|
699
|
+
followUpQueuePolicy?: "respect-mode" | "sequential";
|
|
682
700
|
}): Promise<void>;
|
|
683
701
|
/** Remove undelivered queued custom messages matching `predicate` from executable queues and tagged display mirrors. */
|
|
684
702
|
purgeQueuedCustomMessages(predicate: (message: CustomMessage) => boolean): PurgeQueuedCustomMessagesResult;
|
|
@@ -834,7 +852,7 @@ export declare class AgentSession {
|
|
|
834
852
|
getAvailableModels(): Model[];
|
|
835
853
|
/**
|
|
836
854
|
* Set thinking level.
|
|
837
|
-
* Saves the effective metadata-clamped level to session and settings
|
|
855
|
+
* Saves the effective metadata-clamped level to the session, and to settings when requested.
|
|
838
856
|
*/
|
|
839
857
|
setThinkingLevel(level: ThinkingLevel | undefined, persist?: boolean): void;
|
|
840
858
|
/**
|
|
@@ -932,6 +950,7 @@ export declare class AgentSession {
|
|
|
932
950
|
prepareContributionPrep(options?: ContributionPrepOptions): Promise<ContributionPrepResult>;
|
|
933
951
|
/** Test seam: override the emergency-compaction resource sampler so tests never read real RSS. */
|
|
934
952
|
setResourceSampler(sampler: () => EmergencyCompactionSample): void;
|
|
953
|
+
setRetainedMemorySampler(sampler: (() => RetainedMemorySample) | undefined): void;
|
|
935
954
|
/**
|
|
936
955
|
* Toggle auto-compaction setting.
|
|
937
956
|
*/
|
|
@@ -535,6 +535,7 @@ export declare class SessionManager {
|
|
|
535
535
|
getInjectedTtsrRules(): string[];
|
|
536
536
|
getLeafId(): string | null;
|
|
537
537
|
getLeafEntry(): SessionEntry | undefined;
|
|
538
|
+
getResidentImageBytes(): number;
|
|
538
539
|
/**
|
|
539
540
|
* Get the most recent model role from the current session path.
|
|
540
541
|
* Returns undefined if no model change has been recorded.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AgentTool, AgentToolResult } from "@gajae-code/agent-core";
|
|
2
|
+
import * as z from "zod/v4";
|
|
3
|
+
import { type RuntimeSkillDiscoveryCandidate } from "../extensibility/runtime-skill-discovery";
|
|
4
|
+
import type { ToolSession } from ".";
|
|
5
|
+
declare const skillDiscoverySchema: z.ZodObject<{
|
|
6
|
+
query: z.ZodOptional<z.ZodString>;
|
|
7
|
+
source: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
8
|
+
all: "all";
|
|
9
|
+
project: "project";
|
|
10
|
+
user: "user";
|
|
11
|
+
}>>>;
|
|
12
|
+
limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
export type SkillDiscoveryToolInput = z.infer<typeof skillDiscoverySchema>;
|
|
15
|
+
export interface SkillDiscoveryToolDetails {
|
|
16
|
+
candidates: RuntimeSkillDiscoveryCandidate[];
|
|
17
|
+
count: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class SkillDiscoveryTool implements AgentTool<typeof skillDiscoverySchema, SkillDiscoveryToolDetails> {
|
|
20
|
+
#private;
|
|
21
|
+
readonly name = "skill_discovery";
|
|
22
|
+
readonly label = "SkillDiscovery";
|
|
23
|
+
readonly summary = "Discover project and user runtime skills by thin metadata";
|
|
24
|
+
readonly loadMode = "essential";
|
|
25
|
+
readonly description: string;
|
|
26
|
+
readonly parameters: z.ZodObject<{
|
|
27
|
+
query: z.ZodOptional<z.ZodString>;
|
|
28
|
+
source: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
29
|
+
all: "all";
|
|
30
|
+
project: "project";
|
|
31
|
+
user: "user";
|
|
32
|
+
}>>>;
|
|
33
|
+
limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
readonly strict = true;
|
|
36
|
+
constructor(session: ToolSession);
|
|
37
|
+
static createIf(session: ToolSession): SkillDiscoveryTool | null;
|
|
38
|
+
execute(_toolCallId: string, input: SkillDiscoveryToolInput, signal?: AbortSignal): Promise<AgentToolResult<SkillDiscoveryToolDetails>>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
* Lets the agent hand off to another available skill in the current turn. The
|
|
5
5
|
* callee's SKILL.md is dispatched through the same custom-message path used by
|
|
6
6
|
* `/skill:<name>` typing, as a user-attribution message delivered same-turn
|
|
7
|
-
* (without `deliverAs: "nextTurn"`).
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* (without `deliverAs: "nextTurn"`). When the caller is one of the canonical
|
|
8
|
+
* workflow skills, the tool first runs the native state handoff so workflow
|
|
9
|
+
* mode-state and `skill-active-state.json` transition atomically. Runtime
|
|
10
|
+
* project/user skills have no native workflow mode-state, so they are dispatched
|
|
11
|
+
* directly and tracked by the prompt observer instead.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
* `{complete, completed, handoff, failed, cancelled, canceled, inactive}`.
|
|
14
|
-
* agent declares readiness either by writing `current_phase: "handoff"` to
|
|
15
|
-
* mode-state or by running the handoff verb directly.
|
|
13
|
+
* Canonical workflow chaining is refused unless the caller's `current_phase` is
|
|
14
|
+
* in `{complete, completed, handoff, failed, cancelled, canceled, inactive}`.
|
|
15
|
+
* The agent declares readiness either by writing `current_phase: "handoff"` to
|
|
16
|
+
* its mode-state or by running the handoff verb directly.
|
|
16
17
|
*/
|
|
17
18
|
import type { AgentTool, AgentToolResult } from "@gajae-code/agent-core";
|
|
18
19
|
import * as z from "zod/v4";
|
|
@@ -23,8 +23,10 @@ export interface ResolvePastedImagePathOptions extends DecodePastedPathOptions {
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function decodePastedPathCandidate(text: string, options?: DecodePastedPathOptions): string | undefined;
|
|
25
25
|
/**
|
|
26
|
-
* Returns the resolved path when the whole pasted text is a
|
|
27
|
-
* existing image file
|
|
28
|
-
*
|
|
26
|
+
* Returns the resolved path when the whole pasted text is a recognized clipboard
|
|
27
|
+
* temp path to an existing image file, otherwise `undefined` (the paste is
|
|
28
|
+
* inserted as text). Arbitrary saved image paths are not auto-attached here;
|
|
29
|
+
* users attach them explicitly with `@path/to/image.png`.
|
|
29
30
|
*/
|
|
30
31
|
export declare function resolvePastedImagePath(text: string, options?: ResolvePastedImagePathOptions): string | undefined;
|
|
32
|
+
export declare function formatPastedImageReference(placeholder: string, imagePath: string): string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"description": "Gajae Code CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"@agentclientprotocol/sdk": "0.21.0",
|
|
50
50
|
"@babel/parser": "^7.29.3",
|
|
51
51
|
"@mozilla/readability": "^0.6.0",
|
|
52
|
-
"@gajae-code/stats": "0.9.
|
|
53
|
-
"@gajae-code/agent-core": "0.9.
|
|
54
|
-
"@gajae-code/ai": "0.9.
|
|
55
|
-
"@gajae-code/natives": "0.9.
|
|
56
|
-
"@gajae-code/tui": "0.9.
|
|
57
|
-
"@gajae-code/utils": "0.9.
|
|
52
|
+
"@gajae-code/stats": "0.9.3",
|
|
53
|
+
"@gajae-code/agent-core": "0.9.3",
|
|
54
|
+
"@gajae-code/ai": "0.9.3",
|
|
55
|
+
"@gajae-code/natives": "0.9.3",
|
|
56
|
+
"@gajae-code/tui": "0.9.3",
|
|
57
|
+
"@gajae-code/utils": "0.9.3",
|
|
58
58
|
"@puppeteer/browsers": "^2.13.0",
|
|
59
59
|
"@types/turndown": "5.0.6",
|
|
60
60
|
"@xterm/headless": "^6.0.0",
|
|
@@ -85,6 +85,10 @@
|
|
|
85
85
|
"README.md",
|
|
86
86
|
"CHANGELOG.md",
|
|
87
87
|
"vendor",
|
|
88
|
+
"!vendor/insane-search/engine/tests/**",
|
|
89
|
+
"!src/export/html/template.html",
|
|
90
|
+
"!src/export/html/template.css",
|
|
91
|
+
"!src/export/html/template.js",
|
|
88
92
|
"dist/types"
|
|
89
93
|
],
|
|
90
94
|
"exports": {
|
package/scripts/build-binary.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
+
import { buildDevCompileArgs } from "./compile-args";
|
|
4
5
|
|
|
5
6
|
const packageDir = path.join(import.meta.dir, "..");
|
|
6
7
|
const outputPath = path.join(packageDir, "dist", "gjc");
|
|
@@ -34,46 +35,7 @@ async function main(): Promise<void> {
|
|
|
34
35
|
await runCommand(["bun", "--cwd=../natives", "run", "embed:native"]);
|
|
35
36
|
try {
|
|
36
37
|
const buildEnv = shouldAdhocSignDarwinBinary() ? { ...Bun.env, BUN_NO_CODESIGN_MACHO_BINARY: "1" } : Bun.env;
|
|
37
|
-
await runCommand(
|
|
38
|
-
[
|
|
39
|
-
"bun",
|
|
40
|
-
"build",
|
|
41
|
-
"--compile",
|
|
42
|
-
// Minify shrinks the bundled JS the compiled binary must parse at
|
|
43
|
-
// startup (302MB → ~114MB --help RSS measured on darwin-arm64).
|
|
44
|
-
// --keep-names below preserves identifiers for error reports.
|
|
45
|
-
"--minify",
|
|
46
|
-
"--no-compile-autoload-bunfig",
|
|
47
|
-
"--no-compile-autoload-dotenv",
|
|
48
|
-
"--no-compile-autoload-tsconfig",
|
|
49
|
-
"--no-compile-autoload-package-json",
|
|
50
|
-
"--keep-names",
|
|
51
|
-
"--define",
|
|
52
|
-
'process.env.PI_COMPILED="true"',
|
|
53
|
-
"--external",
|
|
54
|
-
"mupdf",
|
|
55
|
-
"--root",
|
|
56
|
-
"../..",
|
|
57
|
-
"./src/cli.ts",
|
|
58
|
-
// Worker entrypoints. Bun's `--compile` discovers the literal in
|
|
59
|
-
// `new Worker("…", …)` at each spawn site, but only actually
|
|
60
|
-
// emits the worker into the bunfs root when it is listed here as
|
|
61
|
-
// an explicit additional entry. Paths are relative to this
|
|
62
|
-
// script's cwd (packages/coding-agent) and the `--root` above
|
|
63
|
-
// (../..) makes them appear inside the binary at
|
|
64
|
-
// `/$bunfs/root/packages/<pkg>/src/<worker>.js`, which is
|
|
65
|
-
// exactly what the literals at the spawn sites resolve to.
|
|
66
|
-
"../stats/src/sync-worker.ts",
|
|
67
|
-
"./src/tools/browser/tab-worker-entry.ts",
|
|
68
|
-
"./src/eval/js/worker-entry.ts",
|
|
69
|
-
// Hidden notify daemon CLI (loaded via dynamic import from notify-cli); list it
|
|
70
|
-
// explicitly so Bun standalone keeps `gjc notify daemon-internal` usable.
|
|
71
|
-
"./src/notifications/telegram-daemon-cli.ts",
|
|
72
|
-
"--outfile",
|
|
73
|
-
"dist/gjc",
|
|
74
|
-
],
|
|
75
|
-
buildEnv,
|
|
76
|
-
);
|
|
38
|
+
await runCommand(buildDevCompileArgs(), buildEnv);
|
|
77
39
|
|
|
78
40
|
await stageWorkspaceNativeAddons();
|
|
79
41
|
// Bun 1.3.12 emits a truncated Mach-O signature on darwin builds.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export interface CompileArgOptions {
|
|
2
|
+
root: string;
|
|
3
|
+
entrypoints: string[];
|
|
4
|
+
outfile: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
defines?: string[];
|
|
7
|
+
externals?: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const compileAutoloadDisableFlags = [
|
|
11
|
+
"--no-compile-autoload-bunfig",
|
|
12
|
+
"--no-compile-autoload-dotenv",
|
|
13
|
+
"--no-compile-autoload-tsconfig",
|
|
14
|
+
"--no-compile-autoload-package-json",
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export const compiledDefineFlags = ['process.env.PI_COMPILED="true"'];
|
|
18
|
+
export const compiledExternalPackages = ["mupdf"];
|
|
19
|
+
|
|
20
|
+
export const releaseEntrypoints = [
|
|
21
|
+
"./packages/coding-agent/src/cli.ts",
|
|
22
|
+
"./packages/stats/src/sync-worker.ts",
|
|
23
|
+
"./packages/coding-agent/src/tools/browser/tab-worker-entry.ts",
|
|
24
|
+
"./packages/coding-agent/src/eval/js/worker-entry.ts",
|
|
25
|
+
"./packages/natives/native/index.js",
|
|
26
|
+
"./packages/coding-agent/src/notifications/telegram-daemon-cli.ts",
|
|
27
|
+
"./packages/ai/src/models.json",
|
|
28
|
+
"./node_modules/handlebars/lib/index.js",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const devEntrypoints = [
|
|
32
|
+
"./src/cli.ts",
|
|
33
|
+
"../stats/src/sync-worker.ts",
|
|
34
|
+
"./src/tools/browser/tab-worker-entry.ts",
|
|
35
|
+
"./src/eval/js/worker-entry.ts",
|
|
36
|
+
"./src/notifications/telegram-daemon-cli.ts",
|
|
37
|
+
"../ai/src/models.json",
|
|
38
|
+
"../../node_modules/handlebars/lib/index.js",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export function buildReleaseCompileArgs(target: string, outfile: string): string[] {
|
|
42
|
+
return buildCompileArgs({
|
|
43
|
+
root: ".",
|
|
44
|
+
entrypoints: releaseEntrypoints,
|
|
45
|
+
outfile,
|
|
46
|
+
target,
|
|
47
|
+
defines: compiledDefineFlags,
|
|
48
|
+
externals: compiledExternalPackages,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function buildDevCompileArgs(outfile = "dist/gjc"): string[] {
|
|
53
|
+
return buildCompileArgs({
|
|
54
|
+
root: "../..",
|
|
55
|
+
entrypoints: devEntrypoints,
|
|
56
|
+
outfile,
|
|
57
|
+
defines: compiledDefineFlags,
|
|
58
|
+
externals: compiledExternalPackages,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function buildCompileArgs(options: CompileArgOptions): string[] {
|
|
63
|
+
const args = [
|
|
64
|
+
"bun",
|
|
65
|
+
"build",
|
|
66
|
+
"--compile",
|
|
67
|
+
// Minify shrinks the bundled JS the compiled binary must parse at
|
|
68
|
+
// startup (302MB → ~114MB --help RSS measured on darwin-arm64).
|
|
69
|
+
// --keep-names below preserves identifiers for error reports.
|
|
70
|
+
"--minify",
|
|
71
|
+
...compileAutoloadDisableFlags,
|
|
72
|
+
"--keep-names",
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
for (const define of options.defines ?? []) {
|
|
76
|
+
args.push("--define", define);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
args.push("--root", options.root);
|
|
80
|
+
|
|
81
|
+
for (const external of options.externals ?? []) {
|
|
82
|
+
args.push("--external", external);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options.target) {
|
|
86
|
+
args.push("--target", options.target);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
args.push(...options.entrypoints, "--outfile", options.outfile);
|
|
90
|
+
return args;
|
|
91
|
+
}
|
|
@@ -58,6 +58,7 @@ const mapEntries = docsWithContent
|
|
|
58
58
|
.join("\n");
|
|
59
59
|
const output = [
|
|
60
60
|
"// Auto-generated by scripts/generate-docs-index.ts - DO NOT EDIT",
|
|
61
|
+
`Reflect.set(globalThis, Symbol.for("gjc.docs-index.generated.loaded"), true);`,
|
|
61
62
|
"",
|
|
62
63
|
`export const EMBEDDED_DOC_FILENAMES: readonly string[] = ${filenamesLiteral};`,
|
|
63
64
|
"",
|
package/src/capability/mcp.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface MCPServer {
|
|
|
15
15
|
name: string;
|
|
16
16
|
/** Whether this server is enabled (default: true) */
|
|
17
17
|
enabled?: boolean;
|
|
18
|
-
/** Whether
|
|
18
|
+
/** Whether explicit runtime MCP consumers should connect automatically (default: true) */
|
|
19
19
|
autoload?: boolean;
|
|
20
20
|
/** Connection timeout in milliseconds */
|
|
21
21
|
timeout?: number;
|
|
@@ -25,6 +25,8 @@ export interface MCPServer {
|
|
|
25
25
|
args?: string[];
|
|
26
26
|
/** Environment variables */
|
|
27
27
|
env?: Record<string, string>;
|
|
28
|
+
/** Whether explicit stdio runtime consumers should avoid inheriting host environment */
|
|
29
|
+
noInheritEnv?: boolean;
|
|
28
30
|
/** Working directory for stdio transport */
|
|
29
31
|
cwd?: string;
|
|
30
32
|
/** URL (for HTTP/SSE transport) */
|
package/src/cli/args.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { type Effort, THINKING_EFFORTS } from "@gajae-code/ai";
|
|
5
5
|
import { APP_NAME, CONFIG_DIR_NAME, logger } from "@gajae-code/utils";
|
|
6
|
+
import { CliParseError } from "@gajae-code/utils/cli";
|
|
6
7
|
import chalk from "chalk";
|
|
7
8
|
import { parseEffort } from "../thinking";
|
|
8
9
|
import { BUILTIN_TOOLS } from "../tools";
|
|
@@ -20,6 +21,7 @@ export interface Args {
|
|
|
20
21
|
mpreset?: string;
|
|
21
22
|
default?: boolean;
|
|
22
23
|
apiKey?: string;
|
|
24
|
+
credential?: string;
|
|
23
25
|
systemPrompt?: string;
|
|
24
26
|
appendSystemPrompt?: string;
|
|
25
27
|
thinking?: Effort;
|
|
@@ -136,6 +138,12 @@ export function parseArgs(args: string[]): Args {
|
|
|
136
138
|
result.default = true;
|
|
137
139
|
} else if (arg === "--api-key" && i + 1 < args.length) {
|
|
138
140
|
result.apiKey = args[++i];
|
|
141
|
+
} else if (arg === "--credential") {
|
|
142
|
+
const next = args[i + 1];
|
|
143
|
+
if (!next || next.startsWith("-")) {
|
|
144
|
+
throw new CliParseError("--credential requires <selector>");
|
|
145
|
+
}
|
|
146
|
+
result.credential = args[++i];
|
|
139
147
|
} else if (arg === "--system-prompt" && i + 1 < args.length) {
|
|
140
148
|
result.systemPrompt = args[++i];
|
|
141
149
|
} else if (arg === "--append-system-prompt" && i + 1 < args.length) {
|
package/src/cli/mcp-cli.ts
CHANGED
|
@@ -37,14 +37,27 @@ interface ScopedPath {
|
|
|
37
37
|
path: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
interface RuntimeDisclosure {
|
|
41
|
+
runtimeStatus: "storage-only";
|
|
42
|
+
runtimeLoadedByStandalone: false;
|
|
43
|
+
runtimeNote: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
interface RedactedServerEntry {
|
|
41
47
|
name: string;
|
|
42
48
|
config: MCPServerConfig;
|
|
43
49
|
}
|
|
44
50
|
|
|
51
|
+
interface RuntimeRedactedServerEntry extends RedactedServerEntry, RuntimeDisclosure {}
|
|
52
|
+
|
|
45
53
|
const REDACTED = "<redacted>";
|
|
46
54
|
const SENSITIVE_KEY_PATTERN =
|
|
47
55
|
/(?:token|secret|key|credential|password|passwd|pwd|authorization|auth|bearer|cookie|session)/i;
|
|
56
|
+
const STORAGE_ONLY_RUNTIME_DISCLOSURE: RuntimeDisclosure = {
|
|
57
|
+
runtimeStatus: "storage-only",
|
|
58
|
+
runtimeLoadedByStandalone: false,
|
|
59
|
+
runtimeNote: "Stored MCP registrations are not loaded by normal standalone gjc sessions today.",
|
|
60
|
+
};
|
|
48
61
|
|
|
49
62
|
function resolvePath(args: MCPCommandArgs): ScopedPath {
|
|
50
63
|
const scope = args.flags.project ? "project" : "user";
|
|
@@ -128,6 +141,50 @@ function redactRecord(
|
|
|
128
141
|
);
|
|
129
142
|
}
|
|
130
143
|
|
|
144
|
+
function redactUrl(value: string | undefined): string | undefined {
|
|
145
|
+
if (!value) return value;
|
|
146
|
+
try {
|
|
147
|
+
const url = new URL(value);
|
|
148
|
+
if (url.username) url.username = REDACTED;
|
|
149
|
+
if (url.password) url.password = REDACTED;
|
|
150
|
+
if (url.search) {
|
|
151
|
+
for (const key of Array.from(url.searchParams.keys())) {
|
|
152
|
+
url.searchParams.set(key, REDACTED);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
url.hash = "";
|
|
156
|
+
return url.toString();
|
|
157
|
+
} catch {
|
|
158
|
+
return SENSITIVE_KEY_PATTERN.test(value) ? REDACTED : value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function redactArgs(args: string[] | undefined): string[] | undefined {
|
|
163
|
+
if (!args) return undefined;
|
|
164
|
+
const redacted: string[] = [];
|
|
165
|
+
let redactNext = false;
|
|
166
|
+
for (const arg of args) {
|
|
167
|
+
if (redactNext) {
|
|
168
|
+
redacted.push(REDACTED);
|
|
169
|
+
redactNext = false;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const equalsIndex = arg.indexOf("=");
|
|
173
|
+
if (equalsIndex > 0) {
|
|
174
|
+
const key = arg.slice(0, equalsIndex);
|
|
175
|
+
redacted.push(SENSITIVE_KEY_PATTERN.test(key) ? `${key}=${REDACTED}` : arg);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (arg.startsWith("-") && SENSITIVE_KEY_PATTERN.test(arg)) {
|
|
179
|
+
redacted.push(arg);
|
|
180
|
+
redactNext = true;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
redacted.push(SENSITIVE_KEY_PATTERN.test(arg) ? REDACTED : arg);
|
|
184
|
+
}
|
|
185
|
+
return redacted;
|
|
186
|
+
}
|
|
187
|
+
|
|
131
188
|
export function redactMCPServerConfig(config: MCPServerConfig): MCPServerConfig {
|
|
132
189
|
const redacted = { ...config } as MCPServerConfig;
|
|
133
190
|
if ("env" in redacted) {
|
|
@@ -138,11 +195,19 @@ export function redactMCPServerConfig(config: MCPServerConfig): MCPServerConfig
|
|
|
138
195
|
const headers = redactRecord(redacted.headers, true);
|
|
139
196
|
if (headers) redacted.headers = headers;
|
|
140
197
|
}
|
|
198
|
+
if ("url" in redacted) {
|
|
199
|
+
const url = redactUrl(redacted.url);
|
|
200
|
+
if (url) redacted.url = url;
|
|
201
|
+
}
|
|
202
|
+
if ("args" in redacted) {
|
|
203
|
+
const args = redactArgs(redacted.args);
|
|
204
|
+
if (args) redacted.args = args;
|
|
205
|
+
}
|
|
141
206
|
if (redacted.auth) {
|
|
142
207
|
redacted.auth = {
|
|
143
208
|
type: redacted.auth.type,
|
|
144
209
|
credentialId: redacted.auth.credentialId ? REDACTED : undefined,
|
|
145
|
-
tokenUrl: redacted.auth.tokenUrl,
|
|
210
|
+
tokenUrl: redactUrl(redacted.auth.tokenUrl),
|
|
146
211
|
clientId: redacted.auth.clientId ? REDACTED : undefined,
|
|
147
212
|
clientSecret: redacted.auth.clientSecret ? REDACTED : undefined,
|
|
148
213
|
};
|
|
@@ -151,7 +216,7 @@ export function redactMCPServerConfig(config: MCPServerConfig): MCPServerConfig
|
|
|
151
216
|
redacted.oauth = {
|
|
152
217
|
clientId: redacted.oauth.clientId ? REDACTED : undefined,
|
|
153
218
|
clientSecret: redacted.oauth.clientSecret ? REDACTED : undefined,
|
|
154
|
-
redirectUri: redacted.oauth.redirectUri,
|
|
219
|
+
redirectUri: redactUrl(redacted.oauth.redirectUri),
|
|
155
220
|
callbackPort: redacted.oauth.callbackPort,
|
|
156
221
|
callbackPath: redacted.oauth.callbackPath,
|
|
157
222
|
};
|
|
@@ -159,10 +224,14 @@ export function redactMCPServerConfig(config: MCPServerConfig): MCPServerConfig
|
|
|
159
224
|
return redacted;
|
|
160
225
|
}
|
|
161
226
|
|
|
162
|
-
function
|
|
227
|
+
function withRuntimeDisclosure<T extends object>(value: T): T & RuntimeDisclosure {
|
|
228
|
+
return { ...value, ...STORAGE_ONLY_RUNTIME_DISCLOSURE };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function collectEntries(config: MCPConfigFile): RuntimeRedactedServerEntry[] {
|
|
163
232
|
return Object.entries(config.mcpServers ?? {})
|
|
164
233
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
165
|
-
.map(([name, serverConfig]) => ({ name, config: redactMCPServerConfig(serverConfig) }));
|
|
234
|
+
.map(([name, serverConfig]) => withRuntimeDisclosure({ name, config: redactMCPServerConfig(serverConfig) }));
|
|
166
235
|
}
|
|
167
236
|
|
|
168
237
|
function writeJson(value: unknown): void {
|
|
@@ -188,37 +257,46 @@ async function runAdd(args: MCPCommandArgs, scoped: ScopedPath): Promise<void> {
|
|
|
188
257
|
const result = await upsertMCPServer(scoped.path, args.name, config, { force: args.flags.force });
|
|
189
258
|
const redacted = redactMCPServerConfig(config);
|
|
190
259
|
if (args.flags.json) {
|
|
191
|
-
writeJson(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
260
|
+
writeJson(
|
|
261
|
+
withRuntimeDisclosure({
|
|
262
|
+
action: "add",
|
|
263
|
+
status: result.status,
|
|
264
|
+
name: args.name,
|
|
265
|
+
scope: scoped.scope,
|
|
266
|
+
path: scoped.path,
|
|
267
|
+
config: redacted,
|
|
268
|
+
}),
|
|
269
|
+
);
|
|
199
270
|
return;
|
|
200
271
|
}
|
|
201
272
|
if (result.status === "skipped") {
|
|
202
273
|
process.stdout.write(
|
|
203
|
-
`MCP server "${args.name}" already exists in ${scoped.scope} config. Pass --force to overwrite
|
|
274
|
+
`MCP server "${args.name}" already exists in ${scoped.scope} config. Pass --force to overwrite. ` +
|
|
275
|
+
"Status: storage-only; normal standalone gjc sessions do not load stored MCP registrations today.\n",
|
|
204
276
|
);
|
|
205
277
|
return;
|
|
206
278
|
}
|
|
207
|
-
process.stdout.write(
|
|
279
|
+
process.stdout.write(
|
|
280
|
+
`MCP server "${args.name}" ${result.status} in ${scoped.scope} config: ${scoped.path}\nStatus: storage-only; normal standalone gjc sessions do not load stored MCP registrations today.\n`,
|
|
281
|
+
);
|
|
208
282
|
}
|
|
209
283
|
|
|
210
284
|
async function runList(args: MCPCommandArgs, scoped: ScopedPath): Promise<void> {
|
|
211
285
|
const config = await readMCPConfigFile(scoped.path);
|
|
212
286
|
const entries = collectEntries(config);
|
|
213
287
|
if (args.flags.json) {
|
|
214
|
-
writeJson({ action: "list", scope: scoped.scope, path: scoped.path, servers: entries });
|
|
288
|
+
writeJson(withRuntimeDisclosure({ action: "list", scope: scoped.scope, path: scoped.path, servers: entries }));
|
|
215
289
|
return;
|
|
216
290
|
}
|
|
217
291
|
if (entries.length === 0) {
|
|
218
|
-
process.stdout.write(
|
|
292
|
+
process.stdout.write(
|
|
293
|
+
`No MCP servers registered in ${scoped.scope} config: ${scoped.path}\nStatus: storage-only; normal standalone gjc sessions do not load stored MCP registrations today.\n`,
|
|
294
|
+
);
|
|
219
295
|
return;
|
|
220
296
|
}
|
|
221
|
-
process.stdout.write(
|
|
297
|
+
process.stdout.write(
|
|
298
|
+
`MCP servers in ${scoped.scope} config: ${scoped.path}\nStatus: storage-only; normal standalone gjc sessions do not load stored MCP registrations today.\n`,
|
|
299
|
+
);
|
|
222
300
|
for (const entry of entries) {
|
|
223
301
|
process.stdout.write(`${renderDetails(entry)}\n`);
|
|
224
302
|
}
|
|
@@ -233,17 +311,21 @@ async function runRemove(args: MCPCommandArgs, scoped: ScopedPath): Promise<void
|
|
|
233
311
|
await removeMCPServer(scoped.path, args.name);
|
|
234
312
|
const entry = { name: args.name, config: redactMCPServerConfig(existing) };
|
|
235
313
|
if (args.flags.json) {
|
|
236
|
-
writeJson(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
314
|
+
writeJson(
|
|
315
|
+
withRuntimeDisclosure({
|
|
316
|
+
action: "remove",
|
|
317
|
+
status: "removed",
|
|
318
|
+
name: args.name,
|
|
319
|
+
scope: scoped.scope,
|
|
320
|
+
path: scoped.path,
|
|
321
|
+
removed: entry,
|
|
322
|
+
}),
|
|
323
|
+
);
|
|
244
324
|
return;
|
|
245
325
|
}
|
|
246
|
-
process.stdout.write(
|
|
326
|
+
process.stdout.write(
|
|
327
|
+
`Removed MCP server "${args.name}" from ${scoped.scope} config: ${scoped.path}\nStatus: storage-only; normal standalone gjc sessions do not load stored MCP registrations today.\n`,
|
|
328
|
+
);
|
|
247
329
|
process.stdout.write(`${renderDetails(entry)}\n`);
|
|
248
330
|
}
|
|
249
331
|
|