@gajae-code/coding-agent 0.11.6 → 0.11.7
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 +37 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +56 -6
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +5 -5
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +20 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +19 -5
- package/dist/types/main.d.ts +24 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-status-header.d.ts +1 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +1 -1
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +8 -3
- package/dist/types/sdk/bus/telegram-daemon.d.ts +61 -3
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +28 -5
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +21 -7
- package/dist/types/session/internal/managed-session-storage.d.ts +10 -8
- package/dist/types/session/session-manager.d.ts +25 -4
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/tools/fetch.d.ts +5 -8
- package/dist/types/tools/image-gen.d.ts +16 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -8
- package/scripts/generate-sdk-operation-inventory.ts +2 -0
- package/src/capability/index.ts +50 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +34 -9
- package/src/commands/daemon.ts +22 -5
- package/src/commands/sdk.ts +42 -9
- package/src/config/keybindings.ts +1 -1
- package/src/config/model-profiles.ts +18 -0
- package/src/config/settings-schema.ts +57 -6
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +42 -1
- package/src/discovery/ssh.ts +12 -1
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/gjc-runtime/ultragoal-guard.ts +88 -10
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +103 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +275 -12
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +23 -0
- package/src/internal-urls/docs-index.generated.ts +8 -7
- package/src/internal-urls/local-protocol.ts +32 -6
- package/src/main.ts +86 -27
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/model-selector.ts +31 -3
- package/src/modes/components/tool-status-header.ts +6 -1
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/input-controller.ts +31 -0
- package/src/modes/controllers/selector-controller.ts +106 -12
- package/src/modes/interactive-mode.ts +16 -7
- package/src/modes/types.ts +1 -0
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/json-rpc.ts +23 -9
- package/src/runtime-mcp/transports/http.ts +50 -16
- package/src/sdk/bus/chat-daemon-control.ts +4 -3
- package/src/sdk/bus/index.ts +4 -5
- package/src/sdk/bus/lifecycle-commands.ts +16 -7
- package/src/sdk/bus/notification-service.ts +41 -18
- package/src/sdk/bus/telegram-daemon-contract.ts +8 -3
- package/src/sdk/bus/telegram-daemon-control.ts +2 -2
- package/src/sdk/bus/telegram-daemon.ts +1663 -375
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/protocol/operation-inventory.generated.json +11 -0
- package/src/sdk/session.ts +29 -5
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +240 -149
- package/src/session/blob-store.ts +19 -6
- package/src/session/btw-contract.ts +59 -0
- package/src/session/internal/managed-session-scope.ts +313 -57
- package/src/session/internal/managed-session-storage.ts +146 -35
- package/src/session/session-manager.ts +319 -85
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +30 -1
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/tools/ask.ts +1 -1
- package/src/tools/fetch.ts +13 -131
- package/src/tools/image-gen.ts +301 -20
- package/src/tools/read.ts +2 -0
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +138 -27
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
|
@@ -553,7 +553,7 @@ export interface ResolvedSessionMatch {
|
|
|
553
553
|
session: SessionInfo;
|
|
554
554
|
scope: "local" | "global";
|
|
555
555
|
}
|
|
556
|
-
export declare function resolveResumableSession(sessionArg: string, cwd: string, sessionDir?: string, storage?: SessionStorage): Promise<ResolvedSessionMatch | undefined>;
|
|
556
|
+
export declare function resolveResumableSession(sessionArg: string, cwd: string, sessionDir?: string, storage?: SessionStorage, managedAgentDir?: string): Promise<ResolvedSessionMatch | undefined>;
|
|
557
557
|
interface SessionManagerStateSnapshot {
|
|
558
558
|
sessionId: string;
|
|
559
559
|
sessionName: string | undefined;
|
|
@@ -649,6 +649,8 @@ export declare class SessionManager {
|
|
|
649
649
|
/** Get usage statistics across all assistant messages in the session. */
|
|
650
650
|
getUsageStatistics(): UsageStatistics;
|
|
651
651
|
getSessionDir(): string;
|
|
652
|
+
/** Lists picker candidates within this manager's captured destination authority. */
|
|
653
|
+
listForResumePickerReadOnly(): Promise<SessionInfo[]>;
|
|
652
654
|
getSessionId(): string;
|
|
653
655
|
getSessionFile(): string | undefined;
|
|
654
656
|
/**
|
|
@@ -901,8 +903,12 @@ export declare class SessionManager {
|
|
|
901
903
|
static managedDestination(cwd: string, agentDir?: string, storage?: SessionStorage): SessionDestination;
|
|
902
904
|
static explicitDestination(directory: string): SessionDestination;
|
|
903
905
|
static create(cwd: string, destinationInput?: SessionDestinationInput, storage?: SessionStorage): SessionManager;
|
|
906
|
+
/** Prepare a selected candidate using this manager's captured managed destination authority. */
|
|
907
|
+
prepareManagedCandidateForWrite(filePath: string, migrationPolicy: SessionDirectoryMigrationPolicy, expectedIdentity?: ResumeSessionIdentity): Promise<string>;
|
|
908
|
+
/** Prepare a managed candidate and retain its exact post-preparation identity for the next adoption. */
|
|
909
|
+
prepareManagedCandidateForStrictAdoption(filePath: string, migrationPolicy: SessionDirectoryMigrationPolicy, expectedIdentity: ResumeSessionIdentity): Promise<string>;
|
|
904
910
|
/** Resolve a default-managed candidate through binding validation and copy-retain migration before mutation. */
|
|
905
|
-
static prepareManagedCandidateForWrite(filePath: string, migrationPolicy: SessionDirectoryMigrationPolicy): Promise<string>;
|
|
911
|
+
static prepareManagedCandidateForWrite(filePath: string, migrationPolicy: SessionDirectoryMigrationPolicy, destination: SessionDestination, expectedIdentity?: ResumeSessionIdentity): Promise<string>;
|
|
906
912
|
/**
|
|
907
913
|
* Fork a session into the current project directory.
|
|
908
914
|
* Copies history from another session file while creating a new session file in the current sessionDir.
|
|
@@ -916,7 +922,15 @@ export declare class SessionManager {
|
|
|
916
922
|
static open(filePath: string, destinationInput?: SessionDestinationInput, storage?: SessionStorage, migrationPolicy?: SessionDirectoryMigrationPolicy): Promise<SessionManager>;
|
|
917
923
|
static openNestedManaged(filePath: string, destination: SessionDestination, store: ManagedSessionDescendantStore, storage?: SessionStorage): Promise<SessionManager>;
|
|
918
924
|
/**
|
|
919
|
-
* List sessions for the resume picker without recovery or other
|
|
925
|
+
* List default-managed sessions for the resume picker without recovery or other
|
|
926
|
+
* maintenance writes. This is the only picker inventory that includes legacy
|
|
927
|
+
* sibling directories.
|
|
928
|
+
*/
|
|
929
|
+
static listManagedForResumePickerReadOnly(cwd: string, managedAgentDir?: string, storage?: SessionStorage): Promise<SessionInfo[]>;
|
|
930
|
+
/**
|
|
931
|
+
* List sessions from an explicitly supplied picker directory without recovery
|
|
932
|
+
* or other maintenance writes. Unlike managed inventory, this never scans
|
|
933
|
+
* legacy sibling directories.
|
|
920
934
|
*/
|
|
921
935
|
static listForResumePickerReadOnly(cwd: string, sessionDir?: string, storage?: SessionStorage): Promise<SessionInfo[]>;
|
|
922
936
|
/** Tombstone and exact-delete a default-managed candidate. */
|
|
@@ -966,7 +980,13 @@ export declare class SessionManager {
|
|
|
966
980
|
/**
|
|
967
981
|
* List all sessions across all project directories.
|
|
968
982
|
*/
|
|
969
|
-
static listAll(storage?: SessionStorage): Promise<SessionInfo[]>;
|
|
983
|
+
static listAll(storage?: SessionStorage, managedAgentDir?: string): Promise<SessionInfo[]>;
|
|
984
|
+
/**
|
|
985
|
+
* Strict inventory bound to this manager's captured session authority. Managed
|
|
986
|
+
* managers include authorized legacy and current candidates; explicit managers
|
|
987
|
+
* authorize only their exact directory.
|
|
988
|
+
*/
|
|
989
|
+
inventorySessionsStrict(): StrictInventoryResult;
|
|
970
990
|
/**
|
|
971
991
|
* Strict raw scoped inventory for ACP authorization. Enumerates the scoped
|
|
972
992
|
* session directory without suppressing any root/scan/lstat/read/parse/stat/
|
|
@@ -977,6 +997,7 @@ export declare class SessionManager {
|
|
|
977
997
|
static inventorySessionsStrict(cwd: string, options?: {
|
|
978
998
|
sessionDir?: string;
|
|
979
999
|
storage?: SessionStorage;
|
|
1000
|
+
destination?: SessionDestination;
|
|
980
1001
|
}): StrictInventoryResult;
|
|
981
1002
|
/**
|
|
982
1003
|
* Propagate the storage-layer verified hard delete bound to exact identity evidence.
|
|
@@ -73,7 +73,11 @@ export declare function discoverExternalCredentials(options?: DiscoveryOptions):
|
|
|
73
73
|
export declare function formatCredentialSummary(credential: ImportableCredential): string;
|
|
74
74
|
/** Redacted summary lines for an entire discovery result. Never includes secrets. */
|
|
75
75
|
export declare function formatDiscoverySummary(result: CredentialDiscoveryResult): string[];
|
|
76
|
-
|
|
76
|
+
/** Reason shown when automatic OAuth import rejects an unusable discovery record. */
|
|
77
|
+
export declare const INVALID_AUTO_IMPORT_OAUTH_EXPIRY_REASON = "OAuth credential has no valid future expiry";
|
|
78
|
+
export declare function isAutoImportOAuthCredential(credential: ImportableCredential, now?: number): boolean;
|
|
79
|
+
/** Keep rejected OAuth discoveries visible to operators without offering them for automatic import. */
|
|
80
|
+
export declare function getAutoImportOAuthCredentialSkips(credentials: readonly ImportableCredential[], now?: number): SkippedCredential[];
|
|
77
81
|
export declare function filterAutoImportOAuthCredentials(credentials: readonly ImportableCredential[]): ImportableCredential[];
|
|
78
82
|
/**
|
|
79
83
|
* Persist discovered credentials via `upsert`. Each credential is imported
|
|
@@ -37,6 +37,7 @@ interface ProviderPreset {
|
|
|
37
37
|
baseUrl: string;
|
|
38
38
|
apiKeyEnv: string;
|
|
39
39
|
models: readonly string[];
|
|
40
|
+
modelApi?: Readonly<Record<string, ProviderSetupApi>>;
|
|
40
41
|
compat?: ProviderCompatConfig;
|
|
41
42
|
}
|
|
42
43
|
export declare const PROVIDER_PRESETS: readonly ProviderPreset[];
|
|
@@ -47,6 +48,7 @@ export declare function findProviderPreset(value: string | undefined): ProviderP
|
|
|
47
48
|
export declare function formatProviderPresetList(): string;
|
|
48
49
|
export declare function parseModelList(values: readonly string[]): string[];
|
|
49
50
|
export declare function redactSecret(secret: string): string;
|
|
51
|
+
export declare function validateModelApi(modelApi: Readonly<Record<string, string>> | undefined, models: readonly string[], presetId: string): void;
|
|
50
52
|
export declare function addApiCompatibleProvider(input: ProviderSetupInput): Promise<ProviderSetupResult>;
|
|
51
53
|
export declare function formatProviderSetupResult(result: ProviderSetupResult): string;
|
|
52
54
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Settings } from "../config/settings";
|
|
1
2
|
import type { AgentDefinition } from "./types";
|
|
2
3
|
/** Result of agent discovery */
|
|
3
4
|
export interface DiscoveryResult {
|
|
@@ -11,8 +12,9 @@ export declare function filterVisibleAgents(agents: readonly AgentDefinition[]):
|
|
|
11
12
|
* Precedence (highest wins): .gjc project, .gjc user, GJC plugins, then bundled
|
|
12
13
|
*
|
|
13
14
|
* @param cwd - Current working directory for project agent discovery
|
|
15
|
+
* @param activeSettings - Settings used to resolve enabled providers.
|
|
14
16
|
*/
|
|
15
|
-
export declare function discoverAgents(cwd: string, home?: string): Promise<DiscoveryResult>;
|
|
17
|
+
export declare function discoverAgents(cwd: string, home?: string, activeSettings?: Settings): Promise<DiscoveryResult>;
|
|
16
18
|
/**
|
|
17
19
|
* Get an agent by name from discovered agents.
|
|
18
20
|
*/
|
|
@@ -14,6 +14,11 @@ export interface ParsedReadUrlTarget {
|
|
|
14
14
|
limit?: number;
|
|
15
15
|
}
|
|
16
16
|
export declare function parseReadUrlTarget(readPath: string): ParsedReadUrlTarget | null;
|
|
17
|
+
export declare function renderHtmlToText(html: string, signal?: AbortSignal): Promise<{
|
|
18
|
+
content: string;
|
|
19
|
+
ok: boolean;
|
|
20
|
+
method: string;
|
|
21
|
+
}>;
|
|
17
22
|
interface FetchImagePayload {
|
|
18
23
|
data: string;
|
|
19
24
|
mimeType: string;
|
|
@@ -21,14 +26,6 @@ interface FetchImagePayload {
|
|
|
21
26
|
type FetchRenderResult = RenderResult & {
|
|
22
27
|
image?: FetchImagePayload;
|
|
23
28
|
};
|
|
24
|
-
/**
|
|
25
|
-
* Opt-in insane-search fallback for blocked / degraded public URL reads.
|
|
26
|
-
*
|
|
27
|
-
* Returns a finalized `method: "insane"` result on success, or null (so the
|
|
28
|
-
* caller continues with its normal degraded behavior). Fail-closed: no note,
|
|
29
|
-
* guard DNS, dependency probe, or subprocess when raw mode or the opt-in
|
|
30
|
-
* setting is off. The public-URL guard runs BEFORE any probe/spawn.
|
|
31
|
-
*/
|
|
32
29
|
export declare function tryInsaneFallback(args: {
|
|
33
30
|
url: string;
|
|
34
31
|
finalUrl: string;
|
|
@@ -72,6 +72,22 @@ interface InlineImageData {
|
|
|
72
72
|
}
|
|
73
73
|
/** Set the preferred image provider from settings */
|
|
74
74
|
export declare function setPreferredImageProvider(provider: ImageProvider | "auto"): void;
|
|
75
|
+
/** Provider → default image model mapping for auto-binding */
|
|
76
|
+
export declare const IMAGE_PROVIDER_DEFAULTS: Record<string, string>;
|
|
77
|
+
/** Resolved image generation configuration from settings */
|
|
78
|
+
export interface ImageProviderConfig {
|
|
79
|
+
provider: ImageProvider | "auto" | "custom";
|
|
80
|
+
model: string | null;
|
|
81
|
+
customUrl?: string;
|
|
82
|
+
customKey?: string;
|
|
83
|
+
customKeyEnv?: string;
|
|
84
|
+
}
|
|
85
|
+
/** Set the configured image provider + model from settings */
|
|
86
|
+
export declare function setConfiguredImageModel(config: ImageProviderConfig | null): void;
|
|
87
|
+
/** Get the current configured image model (for UI display) */
|
|
88
|
+
export declare function getConfiguredImageModel(): ImageProviderConfig | null;
|
|
89
|
+
/** Resolve the effective image model for a configured provider */
|
|
90
|
+
export declare function resolveImageModel(provider: string, modelOverride: string | null): string;
|
|
75
91
|
export declare function isOpenAIHostedImageModel(model: Model | undefined): model is Model;
|
|
76
92
|
export declare const imageGenTool: CustomTool<typeof imageGenSchema, ImageGenToolDetails>;
|
|
77
93
|
export declare function getImageGenTools(modelRegistry?: ModelRegistry, activeModel?: Model): Promise<Array<CustomTool<typeof imageGenSchema, ImageGenToolDetails>>>;
|
|
@@ -15,6 +15,13 @@ export type SkillDiscoveryToolInput = z.infer<typeof skillDiscoverySchema>;
|
|
|
15
15
|
export interface SkillDiscoveryToolDetails {
|
|
16
16
|
candidates: RuntimeSkillDiscoveryCandidate[];
|
|
17
17
|
count: number;
|
|
18
|
+
/**
|
|
19
|
+
* Present only when zero candidates were returned AND discovery config gates
|
|
20
|
+
* (`skills.enabled` / `skills.enablePiProject` / `skills.enablePiUser`)
|
|
21
|
+
* prevented some or all of the requested scope from being searched. Without
|
|
22
|
+
* this, a disabled config is indistinguishable from "no skills exist".
|
|
23
|
+
*/
|
|
24
|
+
notice?: string;
|
|
18
25
|
}
|
|
19
26
|
export declare class SkillDiscoveryTool implements AgentTool<typeof skillDiscoverySchema, SkillDiscoveryToolDetails> {
|
|
20
27
|
#private;
|
|
@@ -32,6 +32,13 @@ export type SqliteRowLookup = {
|
|
|
32
32
|
} | {
|
|
33
33
|
kind: "rowid";
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Keep raw reads deliberately narrower than SQLite's full grammar. Comments are
|
|
37
|
+
* rejected, and a statement terminator is accepted only as the final
|
|
38
|
+
* non-whitespace character. Quoted semicolons remain ordinary query data.
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateSqliteReadQuery(sql: string): string;
|
|
41
|
+
export declare function enforceSqliteQueryOnly(db: Database): void;
|
|
35
42
|
export declare function parseSqlitePathCandidates(filePath: string): SqlitePathCandidate[];
|
|
36
43
|
export declare function isSqliteFile(absolutePath: string): Promise<boolean>;
|
|
37
44
|
export declare function parseSqliteSelector(subPath: string, queryString: string): SqliteSelector;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
interface ShellSnapshotCacheOptions {
|
|
2
|
+
tempRoot: string;
|
|
3
|
+
home: string | (() => string);
|
|
4
|
+
platform: NodeJS.Platform;
|
|
5
|
+
}
|
|
6
|
+
declare function createShellSnapshotCache(options: ShellSnapshotCacheOptions): {
|
|
7
|
+
getOrCreateSnapshot(shell: string, env: Record<string, string | undefined>): Promise<string | null>;
|
|
8
|
+
cleanup(): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
/** @internal Test-only factory for isolated filesystem and platform assertions. */
|
|
11
|
+
export declare const createShellSnapshotCacheForTesting: typeof createShellSnapshotCache;
|
|
1
12
|
/**
|
|
2
13
|
* Create a shell snapshot, caching the result.
|
|
3
14
|
* Returns the path to the snapshot file, or null if creation failed.
|
|
4
15
|
*/
|
|
5
16
|
export declare function getOrCreateSnapshot(shell: string, env: Record<string, string | undefined>): Promise<string | null>;
|
|
17
|
+
export {};
|
|
@@ -16,6 +16,7 @@ import { spawn as nodeSpawn } from "node:child_process";
|
|
|
16
16
|
export declare const INSANE_VENDOR_DIR: string;
|
|
17
17
|
/** Stable note prefixes — tests assert on these without depending on full stderr. */
|
|
18
18
|
export declare const INSANE_NOTES: {
|
|
19
|
+
readonly securityDisabled: `insane fallback disabled: remote renderer cannot preserve validated network routing`;
|
|
19
20
|
readonly guardBlocked: (reason: string) => string;
|
|
20
21
|
readonly vendorMissing: `insane fallback unavailable: vendor engine missing at packages/coding-agent/vendor/insane-search`;
|
|
21
22
|
readonly noPython: `insane fallback unavailable: python3 not found; install python3 and curl_cffi, then retry with web.insaneFallback=true`;
|
|
@@ -10,6 +10,18 @@ export interface PublicUrlRejected {
|
|
|
10
10
|
export type PublicUrlResult = PublicUrlAccepted | PublicUrlRejected;
|
|
11
11
|
/** Resolver seam so tests can inject DNS results without real lookups. */
|
|
12
12
|
export type AddressResolver = (hostname: string) => Promise<string[]>;
|
|
13
|
+
type ProxyEnvironment = Record<string, string | undefined>;
|
|
14
|
+
export type GuardedPublicFetchResult = {
|
|
15
|
+
ok: true;
|
|
16
|
+
response: Response;
|
|
17
|
+
logicalUrl: URL;
|
|
18
|
+
wireUrl: URL;
|
|
19
|
+
} | {
|
|
20
|
+
ok: false;
|
|
21
|
+
reason: string;
|
|
22
|
+
logicalUrl: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function hasConfiguredProxy(env: ProxyEnvironment): boolean;
|
|
13
25
|
/** True for any address that is not a routable public unicast address. */
|
|
14
26
|
export declare function isPrivateOrSpecialAddress(address: string): boolean;
|
|
15
27
|
/**
|
|
@@ -19,7 +31,12 @@ export declare function isPrivateOrSpecialAddress(address: string): boolean;
|
|
|
19
31
|
*/
|
|
20
32
|
export declare function validatePublicHttpUrl(rawUrl: string, options?: {
|
|
21
33
|
resolver?: AddressResolver;
|
|
34
|
+
signal?: AbortSignal;
|
|
22
35
|
}): Promise<PublicUrlResult>;
|
|
36
|
+
export declare function guardedPublicFetch(rawUrl: string, init?: BunFetchRequestInit, options?: {
|
|
37
|
+
resolver?: AddressResolver;
|
|
38
|
+
}): Promise<GuardedPublicFetchResult>;
|
|
23
39
|
export declare function validatePublicHttpUrlForInsane(rawUrl: string, options?: {
|
|
24
40
|
resolver?: AddressResolver;
|
|
25
41
|
}): Promise<PublicUrlResult>;
|
|
42
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.7",
|
|
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",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
54
54
|
"@babel/parser": "^7.29.3",
|
|
55
55
|
"@mozilla/readability": "^0.6.0",
|
|
56
|
-
"@gajae-code/stats": "0.11.
|
|
57
|
-
"@gajae-code/agent-core": "0.11.
|
|
58
|
-
"@gajae-code/ai": "0.11.
|
|
59
|
-
"@gajae-code/bridge-client": "0.11.
|
|
60
|
-
"@gajae-code/natives": "0.11.
|
|
61
|
-
"@gajae-code/tui": "0.11.
|
|
62
|
-
"@gajae-code/utils": "0.11.
|
|
56
|
+
"@gajae-code/stats": "0.11.7",
|
|
57
|
+
"@gajae-code/agent-core": "0.11.7",
|
|
58
|
+
"@gajae-code/ai": "0.11.7",
|
|
59
|
+
"@gajae-code/bridge-client": "0.11.7",
|
|
60
|
+
"@gajae-code/natives": "0.11.7",
|
|
61
|
+
"@gajae-code/tui": "0.11.7",
|
|
62
|
+
"@gajae-code/utils": "0.11.7",
|
|
63
63
|
"@puppeteer/browsers": "^2.13.0",
|
|
64
64
|
"@types/turndown": "5.0.6",
|
|
65
65
|
"@xterm/headless": "^6.0.0",
|
|
@@ -147,6 +147,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
147
147
|
"agent_session:prepareContributionPrep": "internal accessor/plumbing, not a user-facing control seam",
|
|
148
148
|
"agent_session:setResourceSampler": "internal accessor/plumbing, not a user-facing control seam",
|
|
149
149
|
"agent_session:setRetainedMemorySampler": "internal accessor/plumbing, not a user-facing control seam",
|
|
150
|
+
"agent_session:createBtwConversationScope":
|
|
151
|
+
"internal privacy-scoped side-chat snapshot factory, not a user-facing SDK control seam",
|
|
150
152
|
"agent_session:recordBashResult": "internal accessor/plumbing, not a user-facing control seam",
|
|
151
153
|
"agent_session:executePython": "internal accessor/plumbing, not a user-facing control seam",
|
|
152
154
|
"agent_session:assertEvalExecutionAllowed": "internal accessor/plumbing, not a user-facing control seam",
|
package/src/capability/index.ts
CHANGED
|
@@ -41,6 +41,8 @@ const disabledProviders = new Set<string>();
|
|
|
41
41
|
|
|
42
42
|
/** Settings manager for persistence (if set) */
|
|
43
43
|
let settings: Settings | null = null;
|
|
44
|
+
/** Session-local settings keyed by normalized working directory. */
|
|
45
|
+
const settingsByCwd = new Map<string, Settings>();
|
|
44
46
|
|
|
45
47
|
// =============================================================================
|
|
46
48
|
// Registration API
|
|
@@ -208,8 +210,9 @@ async function loadImpl<T>(
|
|
|
208
210
|
* Filter providers based on options and disabled state.
|
|
209
211
|
*/
|
|
210
212
|
function filterProviders<T>(capability: Capability<T>, options: LoadOptions): Provider<T>[] {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
const activeSettings = options.settings ?? settingsByCwd.get(path.normalize(options.cwd ?? getProjectDir()));
|
|
214
|
+
const activeDisabledProviders = new Set(activeSettings?.get("disabledProviders") ?? disabledProviders);
|
|
215
|
+
let providers = (capability.providers as Provider<T>[]).filter(p => !activeDisabledProviders.has(p.id));
|
|
213
216
|
if (options.providers) {
|
|
214
217
|
const allowed = new Set(options.providers);
|
|
215
218
|
providers = providers.filter(p => allowed.has(p.id));
|
|
@@ -249,63 +252,68 @@ export async function loadCapability<T>(capabilityId: string, options: LoadOptio
|
|
|
249
252
|
* Call this once on startup to enable persistent provider state.
|
|
250
253
|
*/
|
|
251
254
|
export function initializeWithSettings(activeSettings: Settings): void {
|
|
255
|
+
settingsByCwd.set(path.normalize(activeSettings.getCwd()), activeSettings);
|
|
252
256
|
settings = activeSettings;
|
|
253
|
-
|
|
254
|
-
const disabled = settings.get("disabledProviders");
|
|
257
|
+
const disabled = activeSettings.get("disabledProviders");
|
|
255
258
|
disabledProviders.clear();
|
|
256
|
-
for (const id of disabled)
|
|
257
|
-
disabledProviders.add(id);
|
|
258
|
-
}
|
|
259
|
+
for (const id of disabled) disabledProviders.add(id);
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
/**
|
|
262
263
|
* Persist current disabled providers to settings.
|
|
263
264
|
*/
|
|
264
|
-
function persistDisabledProviders(): void {
|
|
265
|
-
|
|
266
|
-
settings.set("disabledProviders", Array.from(disabledProviders));
|
|
267
|
-
}
|
|
265
|
+
function persistDisabledProviders(activeSettings: Settings, providers: ReadonlySet<string>): void {
|
|
266
|
+
activeSettings.set("disabledProviders", Array.from(providers));
|
|
268
267
|
}
|
|
269
268
|
|
|
270
|
-
/**
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
269
|
+
/** Disable a provider for the supplied session settings. */
|
|
270
|
+
export function disableProvider(
|
|
271
|
+
providerId: string,
|
|
272
|
+
activeSettings: Settings = settings ??
|
|
273
|
+
(() => {
|
|
274
|
+
throw new Error("Capability settings unavailable");
|
|
275
|
+
})(),
|
|
276
|
+
): void {
|
|
277
|
+
const providers = new Set(activeSettings.get("disabledProviders"));
|
|
278
|
+
providers.add(providerId);
|
|
279
|
+
persistDisabledProviders(activeSettings, providers);
|
|
276
280
|
}
|
|
277
281
|
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
/** Enable a provider for the supplied session settings. */
|
|
283
|
+
export function enableProvider(
|
|
284
|
+
providerId: string,
|
|
285
|
+
activeSettings: Settings = settings ??
|
|
286
|
+
(() => {
|
|
287
|
+
throw new Error("Capability settings unavailable");
|
|
288
|
+
})(),
|
|
289
|
+
): void {
|
|
290
|
+
const providers = new Set(activeSettings.get("disabledProviders"));
|
|
291
|
+
providers.delete(providerId);
|
|
292
|
+
persistDisabledProviders(activeSettings, providers);
|
|
284
293
|
}
|
|
285
294
|
|
|
286
|
-
/**
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
295
|
+
/** Check whether a provider is enabled by the supplied session settings. */
|
|
296
|
+
export function isProviderEnabled(
|
|
297
|
+
providerId: string,
|
|
298
|
+
activeSettings: Settings | undefined = settings ?? undefined,
|
|
299
|
+
): boolean {
|
|
300
|
+
return !new Set(activeSettings?.get("disabledProviders") ?? disabledProviders).has(providerId);
|
|
291
301
|
}
|
|
292
302
|
|
|
293
|
-
/**
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
export function getDisabledProviders(): string[] {
|
|
297
|
-
return Array.from(disabledProviders);
|
|
303
|
+
/** Get disabled providers from the supplied session settings. */
|
|
304
|
+
export function getDisabledProviders(activeSettings: Settings | undefined = settings ?? undefined): string[] {
|
|
305
|
+
return [...(activeSettings?.get("disabledProviders") ?? disabledProviders)];
|
|
298
306
|
}
|
|
299
307
|
|
|
300
|
-
/**
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
persistDisabledProviders();
|
|
308
|
+
/** Replace disabled providers for the supplied session settings. */
|
|
309
|
+
export function setDisabledProviders(
|
|
310
|
+
providerIds: string[],
|
|
311
|
+
activeSettings: Settings = settings ??
|
|
312
|
+
(() => {
|
|
313
|
+
throw new Error("Capability settings unavailable");
|
|
314
|
+
})(),
|
|
315
|
+
): void {
|
|
316
|
+
persistDisabledProviders(activeSettings, new Set(providerIds));
|
|
309
317
|
}
|
|
310
318
|
|
|
311
319
|
// =============================================================================
|
package/src/capability/types.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and get back a unified array of MCP servers.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { Settings } from "../config/settings";
|
|
9
10
|
/**
|
|
10
11
|
* Context passed to every provider loader.
|
|
11
12
|
*/
|
|
@@ -72,6 +73,8 @@ export interface LoadOptions {
|
|
|
72
73
|
includeDisabled?: boolean;
|
|
73
74
|
/** Explicit disabled extension IDs to apply instead of settings. */
|
|
74
75
|
disabledExtensions?: string[];
|
|
76
|
+
/** Session settings whose provider policy applies to this load. */
|
|
77
|
+
settings?: Settings;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
package/src/cli/setup-cli.ts
CHANGED
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
} from "../hooks/codex-native-hooks-config";
|
|
19
19
|
import { theme } from "../modes/theme/theme";
|
|
20
20
|
import { formatCredentialAutoImportResult, runExternalCredentialAutoImport } from "../setup/credential-auto-import";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
formatDiscoverySummary,
|
|
23
|
+
getAutoImportOAuthCredentialSkips,
|
|
24
|
+
isAutoImportOAuthCredential,
|
|
25
|
+
} from "../setup/credential-import";
|
|
22
26
|
import {
|
|
23
27
|
formatHermesSetupResult,
|
|
24
28
|
type HermesSetupFlags,
|
|
@@ -596,8 +600,10 @@ export async function handleCredentialsSetup(
|
|
|
596
600
|
trigger: "setup-cli",
|
|
597
601
|
});
|
|
598
602
|
const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
599
|
-
const
|
|
600
|
-
const
|
|
603
|
+
const now = Date.now();
|
|
604
|
+
const candidates = result.importable.filter(credential => isAutoImportOAuthCredential(credential, now));
|
|
605
|
+
const autoImportSkips = getAutoImportOAuthCredentialSkips(result.importable, now);
|
|
606
|
+
const filteredResult = { ...result, importable: candidates, skipped: [...result.skipped, ...autoImportSkips] };
|
|
601
607
|
const redactedPlan = {
|
|
602
608
|
importable: candidates.map(c => ({
|
|
603
609
|
provider: c.provider,
|
|
@@ -607,7 +613,7 @@ export async function handleCredentialsSetup(
|
|
|
607
613
|
expiresAt: c.expiresAt,
|
|
608
614
|
redactedToken: c.redactedToken,
|
|
609
615
|
})),
|
|
610
|
-
skipped:
|
|
616
|
+
skipped: filteredResult.skipped,
|
|
611
617
|
environment: result.environment,
|
|
612
618
|
keychainChecked: flags.keychain === true,
|
|
613
619
|
};
|
package/src/cli.ts
CHANGED
|
@@ -287,9 +287,34 @@ export function normalizeResumeAlias(argv: readonly string[]): string[] {
|
|
|
287
287
|
return argv.length === 1 && argv[0] === "resume" ? ["--resume"] : [...argv];
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
function routeLegacyRootArgv(argv: readonly string[]): string[] | undefined {
|
|
291
|
+
if (argv[0] === "coordinator-mcp") return ["mcp-serve", "coordinator", ...argv.slice(1)];
|
|
292
|
+
if (argv[0] !== "--team") return undefined;
|
|
293
|
+
const sizeValues: string[] = [];
|
|
294
|
+
const remaining: string[] = [];
|
|
295
|
+
for (let index = 1; index < argv.length; index++) {
|
|
296
|
+
const arg = argv[index] ?? "";
|
|
297
|
+
if (arg === "--team-size") {
|
|
298
|
+
sizeValues.push(argv[index + 1] ?? "");
|
|
299
|
+
index++;
|
|
300
|
+
} else if (arg.startsWith("--team-size=")) {
|
|
301
|
+
sizeValues.push(arg.slice("--team-size=".length));
|
|
302
|
+
} else {
|
|
303
|
+
remaining.push(arg);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const size = sizeValues[0];
|
|
307
|
+
if (sizeValues.length !== 1 || !size || !/^[1-9]\d*$/.test(size)) {
|
|
308
|
+
return ["team", "0", "invalid legacy --team-size"];
|
|
309
|
+
}
|
|
310
|
+
return ["team", size, ...remaining];
|
|
311
|
+
}
|
|
312
|
+
|
|
290
313
|
/** Apply the same default-launch routing used by runCli after root fast paths. */
|
|
291
314
|
export function routeRootArgv(argv: readonly string[]): string[] {
|
|
292
315
|
const normalizedArgv = normalizeResumeAlias(argv);
|
|
316
|
+
const legacyArgv = routeLegacyRootArgv(normalizedArgv);
|
|
317
|
+
if (legacyArgv) return legacyArgv;
|
|
293
318
|
const first = normalizedArgv[0];
|
|
294
319
|
return first === "--help" || first === "-h" || first === "--version" || first === "-v" || first === "help"
|
|
295
320
|
? normalizedArgv
|
|
@@ -348,11 +373,9 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
348
373
|
process.exitCode = await runFixtureReport(id);
|
|
349
374
|
return;
|
|
350
375
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
if (hasRootHelpFlag(argv)) {
|
|
376
|
+
const normalizedArgv = normalizeResumeAlias(argv);
|
|
377
|
+
const legacyArgv = routeLegacyRootArgv(normalizedArgv);
|
|
378
|
+
if (!legacyArgv && hasRootHelpFlag(normalizedArgv)) {
|
|
356
379
|
const { renderRootHelp } = await import("@gajae-code/utils/cli");
|
|
357
380
|
const { getExtraHelpText } = await import("./cli/fast-help");
|
|
358
381
|
renderRootHelp({ bin: APP_NAME, version: VERSION, commands: new Map([["launch", RootHelpCommand]]) });
|
|
@@ -362,14 +385,16 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
362
385
|
}
|
|
363
386
|
return;
|
|
364
387
|
}
|
|
365
|
-
if (hasRootVersionFlag(
|
|
388
|
+
if (!legacyArgv && hasRootVersionFlag(normalizedArgv)) {
|
|
366
389
|
process.stdout.write(`${APP_NAME}/${VERSION}\n`);
|
|
367
390
|
return;
|
|
368
391
|
}
|
|
392
|
+
const runArgv = legacyArgv ?? routeRootArgv(normalizedArgv);
|
|
393
|
+
if (isStatsHelpFastPath(runArgv)) {
|
|
394
|
+
showStatsFastHelp();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
369
397
|
await installRuntimeGlobals();
|
|
370
|
-
// --help and --version are handled by run() directly, don't rewrite those.
|
|
371
|
-
// Everything else that isn't a known subcommand routes to "launch".
|
|
372
|
-
const runArgv = routeRootArgv(argv);
|
|
373
398
|
return run({ bin: APP_NAME, version: VERSION, argv: runArgv, commands, help: showHelp });
|
|
374
399
|
}
|
|
375
400
|
|
package/src/commands/daemon.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Manage GJC background daemons (status/list/stop/reload).
|
|
3
3
|
*/
|
|
4
|
-
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
4
|
+
import { Args, CliParseError, Command, Flags } from "@gajae-code/utils/cli";
|
|
5
5
|
import {
|
|
6
6
|
type DaemonCommandAction,
|
|
7
7
|
type DaemonCommandArgs,
|
|
@@ -15,6 +15,18 @@ import { runSdkSessionCli } from "../sdk/cli";
|
|
|
15
15
|
|
|
16
16
|
const ACTIONS = [...DAEMON_ACTION_TOKENS, "discord-internal", "slack-internal", "session"] as const;
|
|
17
17
|
|
|
18
|
+
function parsePositiveTimeout(raw: string | undefined, flagName: string): number | undefined {
|
|
19
|
+
if (raw === undefined) return undefined;
|
|
20
|
+
if (!/^[0-9]+$/.test(raw)) {
|
|
21
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
22
|
+
}
|
|
23
|
+
const value = Number(raw);
|
|
24
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
25
|
+
throw new CliParseError(`Expected ${flagName} to be a positive safe integer, got "${raw}"`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
export default class Daemon extends Command {
|
|
19
31
|
static description =
|
|
20
32
|
"Manage GJC background daemons and SDK sessions. Routine use: `gjc daemon status` to check, `gjc daemon restart` to reload (spawns one if none is running). `stop`/`list` and the escalation flags below are advanced primitives.";
|
|
@@ -41,8 +53,8 @@ export default class Daemon extends Command {
|
|
|
41
53
|
all: Flags.boolean({ description: "Target all registered daemon kinds" }),
|
|
42
54
|
json: Flags.boolean({ description: "Emit JSON output" }),
|
|
43
55
|
force: Flags.boolean({ description: "Allow hard-kill escalation when graceful stop times out" }),
|
|
44
|
-
"graceful-timeout-ms": Flags.
|
|
45
|
-
"kill-timeout-ms": Flags.
|
|
56
|
+
"graceful-timeout-ms": Flags.string({ description: "Cooperative stop timeout before escalation" }),
|
|
57
|
+
"kill-timeout-ms": Flags.string({ description: "Wait for old pid death after SIGKILL" }),
|
|
46
58
|
"spawn-if-stopped": Flags.boolean({ description: "On reload, spawn even when no daemon is running" }),
|
|
47
59
|
smoke: Flags.boolean({ description: "Internal: run worker smoke without configuration or network" }),
|
|
48
60
|
"owner-id": Flags.string({ description: "Internal: daemon owner id" }),
|
|
@@ -64,6 +76,11 @@ export default class Daemon extends Command {
|
|
|
64
76
|
const rawAction = args.action ?? "status";
|
|
65
77
|
const positional = Array.isArray(args.kind) ? args.kind : args.kind ? [args.kind] : [];
|
|
66
78
|
const flagRec = flags as Record<string, unknown>;
|
|
79
|
+
const gracefulTimeoutMs = parsePositiveTimeout(
|
|
80
|
+
flagRec["graceful-timeout-ms"] as string | undefined,
|
|
81
|
+
"--graceful-timeout-ms",
|
|
82
|
+
);
|
|
83
|
+
const killTimeoutMs = parsePositiveTimeout(flagRec["kill-timeout-ms"] as string | undefined, "--kill-timeout-ms");
|
|
67
84
|
if (rawAction === "session") {
|
|
68
85
|
await runSdkSessionCli({
|
|
69
86
|
action: positional[0],
|
|
@@ -91,8 +108,8 @@ export default class Daemon extends Command {
|
|
|
91
108
|
json: Boolean(flags.json),
|
|
92
109
|
force: Boolean(flags.force),
|
|
93
110
|
verbose: Boolean(flags.verbose),
|
|
94
|
-
gracefulTimeoutMs
|
|
95
|
-
killTimeoutMs
|
|
111
|
+
gracefulTimeoutMs,
|
|
112
|
+
killTimeoutMs,
|
|
96
113
|
spawnIfStopped: flagRec["spawn-if-stopped"] as boolean | undefined,
|
|
97
114
|
smoke: Boolean(flags.smoke),
|
|
98
115
|
ownerId: flagRec["owner-id"] as string | undefined,
|