@gajae-code/coding-agent 0.9.1 → 0.9.2
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/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/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/thinking-selector.d.ts +6 -1
- package/dist/types/modes/types.d.ts +1 -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/sdk.d.ts +7 -1
- package/dist/types/session/agent-session.d.ts +6 -3
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/skill-discovery.d.ts +40 -0
- package/package.json +7 -7
- package/src/cli/args.ts +8 -0
- package/src/cli/notify-cli.ts +27 -1
- package/src/cli.ts +5 -0
- package/src/commands/launch.ts +5 -0
- package/src/commands/notify.ts +2 -2
- 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/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/team-runtime.ts +35 -3
- package/src/main.ts +26 -3
- package/src/modes/components/settings-selector.ts +3 -3
- package/src/modes/components/thinking-selector.ts +79 -18
- package/src/modes/controllers/input-controller.ts +50 -9
- package/src/modes/controllers/selector-controller.ts +7 -5
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +48 -15
- 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/runtime-credential-selector.ts +35 -0
- package/src/sdk.ts +68 -5
- package/src/session/agent-session.ts +42 -18
- package/src/system-prompt.ts +4 -6
- package/src/tools/index.ts +4 -0
- package/src/tools/skill-discovery.ts +73 -0
- package/src/tools/skill.ts +15 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.2] - 2026-07-09
|
|
6
|
+
### Added
|
|
7
|
+
|
|
8
|
+
- Added `gjc --credential <selector>` for pinning a stored provider credential by `email:`, `id:`, `account:`, `project:`, or `provider/email:` during a session.
|
|
9
|
+
- Added `--mpreset <profile>` support to Telegram `/session_create`, forwarding both `--mpreset <name>` and `--mpreset=<name>` as split argv to the spawned GJC child.
|
|
10
|
+
- Added the built-in `skill_discovery` tool for runtime discovery of custom project/user skills without injecting the full skill catalog into the core prompt.
|
|
11
|
+
- Pasting or drag-dropping a path to an existing image file now attaches the image and inserts an `[image N]` placeholder, including quoted paths, `file://` URIs, `~/` expansion, spaces, and macOS screenshot narrow no-break spaces.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Finalized notification turn mirrors now default to the bounded full-turn cap so Telegram's existing chunked delivery can send long assistant answers instead of receiving an already-truncated 3500-character summary; `GJC_NOTIFICATIONS_TURN_MAX` remains available to lower the cap for summary-style mirrors, and live previews stay capped as one editable message.
|
|
16
|
+
- `gjc --tmux` now wraps the inner GJC command with a durable `tmux-exit.json` marker next to `runtime-state.json`, so a tmux-resident session that exits before normal runtime-state finalization leaves a public-safe exit timestamp/code for silent-vanish diagnosis (#1746).
|
|
17
|
+
- `gjc --tmux` terminal titles now track live tmux session renames while preserving the friendly project/branch title for untouched generated session ids.
|
|
18
|
+
- Telegram session forum-topic renames now remain retryable after a transient `editForumTopic` failure, so topics do not get stuck at the provisional `GJC <session>` name while the daemon incorrectly records the final title locally.
|
|
19
|
+
- `/effort` selector choices now show the current reasoning effort and mirror `/model` by asking whether to apply the selected effort for the current session or save it as the default, including support for persisting `off`. Default model presets also sync their encoded effort into the persisted effort default so later `/effort` defaults are not overwritten on restart.
|
|
20
|
+
- Composer queue submissions (`Alt+Q` / `app.message.queue`) force one-at-a-time follow-up delivery, including replay after compaction, without disabling broader batch mode for other follow-up callers.
|
|
21
|
+
- `--credential` now rejects a missing selector immediately instead of falling through into session launch with no output.
|
|
22
|
+
- `gjc-session` prompt/monitor postmortem helpers now work on macOS's system Bash/Python, so missing tmux sessions write the public-safe `vanished.json` marker and prompt injection exits through the guarded refusal path.
|
|
23
|
+
|
|
5
24
|
## [0.9.1] - 2026-07-08
|
|
6
25
|
|
|
7
26
|
### Added
|
|
@@ -15,8 +34,12 @@
|
|
|
15
34
|
### Changed
|
|
16
35
|
|
|
17
36
|
- Upgraded the Extragoal review template with a stronger reviewer lane and optional maximalist N-of-N review recipe.
|
|
37
|
+
- Added `--mpreset <profile>` option to the Telegram `/session_create` command, allowing users to specify a model profile preset when creating a session remotely (e.g. `/session_create path /repo --mpreset codex-eco`). Both `--mpreset <name>` and `--mpreset=<name>` forms are supported. The preset is passed as a regular `--mpreset` CLI flag to the spawned `gjc` child, where the existing `applyStartupModelProfiles` flow activates it.
|
|
38
|
+
- Added the built-in `skill_discovery` tool for runtime discovery of custom project `.gjc/skills` and user `~/.gjc/skills` without injecting the full skill catalog into the core prompt; selected discovered skills are loaded narrowly through the existing `skill` invocation path (#1815).
|
|
39
|
+
- Pasting or drag-dropping a path to any existing image file into the interactive editor now attaches the image and inserts an `[image N]` placeholder instead of leaving the raw path in the prompt. Previously this only worked for clipboard temp files (`/tmp/clipboard-*` or `/var/folders/xx/yy/T/clipboard-*`); terminal drag-drop paths — including shell-escaped spaces and the U+202F narrow no-break space in macOS screenshot names — pasted as long raw path text. Quoted paths, `file://` URIs (decoded via Node's `fileURLToPath` semantics, including Windows drive-letter, `file://localhost`, and UNC forms), and `~/` expansion are handled; the whole paste must be a single path to an existing image file whose content carries a supported image signature (PNG/JPEG/GIF/WEBP), so prose containing paths and non-image files with image-looking extensions are inserted unchanged. When attachment still fails (unsupported content, oversized image, load error), the original pasted text is replayed into the editor instead of being consumed.
|
|
18
40
|
|
|
19
41
|
### Fixed
|
|
42
|
+
- Composer queue submissions (`Alt+Q` / `app.message.queue`) now force one-at-a-time follow-up delivery for those queued prompts, including replay after compaction, so they do not collapse into one batched model call even when the broader follow-up mode is set to `all`.
|
|
20
43
|
|
|
21
44
|
- `gjc team` on Windows/psmux now targets the GJC-managed leader session by name instead of trusting the inherited `TMUX_PANE`.
|
|
22
45
|
- Kitty inline images no longer duplicate/stack or paint over transcript text when the diff renderer repaints the image line.
|
|
@@ -36,6 +59,7 @@
|
|
|
36
59
|
- Added `GJC_NOTIFICATIONS_TURN_MAX` to raise the finalized `turn_stream` text cap (default 3500 chars, unchanged) so full long turns reach split-capable clients — the Telegram daemon already fans a long finalized turn across multiple messages via `splitTelegramHtml` — instead of being truncated with an ellipsis at the notification layer. The value is clamped to a finite `[280, 40000]` range: a non-finite or non-positive value (unset, `NaN`, `Infinity`, `<= 0`) falls back to the default, so the cap can never be unbounded. Opt-in and off by default (mirror stays a glanceable per-turn summary); live in-progress frames are intentionally NOT raised so a streaming turn stays one editable preview message rather than fanning across sends.
|
|
37
60
|
|
|
38
61
|
### Fixed
|
|
62
|
+
- Composer-pasted images now follow the visible `[image N]` placeholders at submit time, so deleting a pasted image placeholder with Backspace removes that attachment instead of still sending it to the model or Telegram session mirrors.
|
|
39
63
|
|
|
40
64
|
- Stopped the Hindsight memory backend from injecting stale public-memory-tool guidance into the system prompt. `hindsight/backend.ts`'s `STATIC_INSTRUCTIONS` still instructed the model to "Use `recall`/`retain`/`reflect`", but those tools were removed from the public surface in #341 — they are unregistered in `BUILTIN_TOOLS`/`HIDDEN_TOOLS` and not discoverable — so every Hindsight-backed session advertised three uncallable tools in its injected `# Memory` block. #341 cleaned the local-memory prompts, public docs, and tool registry but never touched the Hindsight backend's own injected block, and its `public-memory-tool-surface.test.ts` guard list omitted `backend.ts`, so the drift went unnoticed. The block now describes the automatic recall/retain lifecycle instead of naming tools, and the regression test now guards `hindsight/backend.ts`.
|
|
41
65
|
- Task subagent output-ID allocation now reserves numeric prefixes from `.jsonl` session artifacts and `.patch` sidecars as well as final `.md` outputs, preventing resumed or partial subagent runs from reusing an existing artifact stem (#1733).
|
package/dist/types/cli/args.d.ts
CHANGED
|
@@ -19,12 +19,17 @@ export interface NotifyCommandDeps {
|
|
|
19
19
|
setupRedact?: boolean;
|
|
20
20
|
setupInteractive?: boolean;
|
|
21
21
|
threadedModePrompt?: (message: string) => Promise<string>;
|
|
22
|
+
tokenPrompt?: () => Promise<string>;
|
|
23
|
+
setExitCode?: (code: number) => void;
|
|
24
|
+
exitProcess?: (code: number) => void;
|
|
22
25
|
}
|
|
23
26
|
export declare function parseNotifyArgs(args: string[]): NotifyCommandArgs | undefined;
|
|
24
27
|
export declare function runNotifyCommand(cmd: NotifyCommandArgs, deps?: NotifyCommandDeps): Promise<void>;
|
|
28
|
+
export declare function runNotifyCliCommand(cmd: NotifyCommandArgs, deps?: NotifyCommandDeps): Promise<void>;
|
|
25
29
|
type TokenPromptInput = NodeJS.ReadStream & {
|
|
26
30
|
isRaw?: boolean;
|
|
27
31
|
setRawMode?: (mode: boolean) => unknown;
|
|
32
|
+
pause?: () => unknown;
|
|
28
33
|
};
|
|
29
34
|
type TokenPromptOutput = Pick<NodeJS.WriteStream, "write">;
|
|
30
35
|
export declare function promptForToken(input?: TokenPromptInput, output?: TokenPromptOutput): Promise<string>;
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -40,6 +40,9 @@ export declare class RootHelpCommand extends Command {
|
|
|
40
40
|
"api-key": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
41
41
|
description: string;
|
|
42
42
|
};
|
|
43
|
+
credential: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
44
|
+
description: string;
|
|
45
|
+
};
|
|
43
46
|
"system-prompt": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
44
47
|
description: string;
|
|
45
48
|
};
|
|
@@ -37,6 +37,9 @@ export default class Index extends Command {
|
|
|
37
37
|
"api-key": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
38
38
|
description: string;
|
|
39
39
|
};
|
|
40
|
+
credential: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
41
|
+
description: string;
|
|
42
|
+
};
|
|
40
43
|
"system-prompt": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
41
44
|
description: string;
|
|
42
45
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
2
|
import type { Api, Model } from "@gajae-code/ai";
|
|
3
3
|
import type { AgentSession } from "../session/agent-session";
|
|
4
4
|
import { type GjcModelAssignmentTargetId, type ModelRegistry } from "./model-registry";
|
|
@@ -16,6 +16,10 @@ export interface PrepareModelProfileActivationOptions {
|
|
|
16
16
|
settings: Pick<Settings, "get">;
|
|
17
17
|
profileName: string;
|
|
18
18
|
}
|
|
19
|
+
export interface ApplyModelProfileActivationOptions {
|
|
20
|
+
persistDefault?: boolean;
|
|
21
|
+
thinkingLevelOverride?: ThinkingLevel;
|
|
22
|
+
}
|
|
19
23
|
export interface PreparedModelProfileActivation {
|
|
20
24
|
profileName: string;
|
|
21
25
|
session: ModelProfileActivationSession & {
|
|
@@ -55,9 +59,7 @@ export declare function materializeActiveModelProfileAssignment(options: Materia
|
|
|
55
59
|
export declare function materializeActiveModelProfileAssignments(options: MaterializeModelProfileAssignmentsOptions): boolean;
|
|
56
60
|
export declare function formatModelProfileCredentialError(profileLabel: string, providers: readonly string[]): string;
|
|
57
61
|
export declare function prepareModelProfileActivation(options: PrepareModelProfileActivationOptions): Promise<PreparedModelProfileActivation>;
|
|
58
|
-
export declare function applyPreparedModelProfileActivation(prepared: PreparedModelProfileActivation, options?:
|
|
59
|
-
persistDefault?: boolean;
|
|
60
|
-
}): Promise<void>;
|
|
62
|
+
export declare function applyPreparedModelProfileActivation(prepared: PreparedModelProfileActivation, options?: ApplyModelProfileActivationOptions): Promise<void>;
|
|
61
63
|
export interface MaterializeModelProfileForDeletionResult {
|
|
62
64
|
modelRoles: Record<string, string>;
|
|
63
65
|
agentModelOverrides: Record<string, string>;
|
|
@@ -75,7 +77,5 @@ export declare function restoreMaterializedModelProfileForDeletion(options: {
|
|
|
75
77
|
session: Pick<ModelProfileActivationSession, "setActiveModelProfile">;
|
|
76
78
|
snapshot: MaterializeModelProfileForDeletionResult;
|
|
77
79
|
}): Promise<void>;
|
|
78
|
-
export declare function activateModelProfile(options: PrepareModelProfileActivationOptions, applyOptions?:
|
|
79
|
-
persistDefault?: boolean;
|
|
80
|
-
}): Promise<void>;
|
|
80
|
+
export declare function activateModelProfile(options: PrepareModelProfileActivationOptions, applyOptions?: ApplyModelProfileActivationOptions): Promise<void>;
|
|
81
81
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Api, type AssistantMessageEventStream, type CacheRetention, type Context, type Model, type ModelRefreshStrategy, type ModelRequestTransform, type SimpleStreamOptions, type ThinkingConfig } from "@gajae-code/ai";
|
|
1
|
+
import { type Api, type AssistantMessageEventStream, type AuthCredentialSelector, type CacheRetention, type Context, type Model, type ModelRefreshStrategy, type ModelRequestTransform, type SimpleStreamOptions, type ThinkingConfig } from "@gajae-code/ai";
|
|
2
2
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "@gajae-code/ai/utils/oauth/types";
|
|
3
3
|
import { type ThemeColor } from "../modes/theme/theme";
|
|
4
4
|
import type { AuthStorage } from "../session/auth-storage";
|
|
@@ -386,11 +386,15 @@ export declare class ModelRegistry {
|
|
|
386
386
|
/**
|
|
387
387
|
* Get API key for a model.
|
|
388
388
|
*/
|
|
389
|
-
getApiKey(model: Model<Api>, sessionId?: string
|
|
389
|
+
getApiKey(model: Model<Api>, sessionId?: string, options?: {
|
|
390
|
+
credentialSelector?: AuthCredentialSelector;
|
|
391
|
+
}): Promise<string | undefined>;
|
|
390
392
|
/**
|
|
391
393
|
* Get API key for a provider (e.g., "openai").
|
|
392
394
|
*/
|
|
393
|
-
getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string
|
|
395
|
+
getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string, options?: {
|
|
396
|
+
credentialSelector?: AuthCredentialSelector;
|
|
397
|
+
}): Promise<string | undefined>;
|
|
394
398
|
/**
|
|
395
399
|
* Check if a model is using OAuth credentials (subscription).
|
|
396
400
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Model resolution, scoping, and initial selection
|
|
3
3
|
*/
|
|
4
4
|
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
5
|
-
import { type Api, type
|
|
5
|
+
import { type Api, type KnownProvider, type Model } from "@gajae-code/ai";
|
|
6
6
|
import { type ModelRegistry, type ModelRole } from "./model-registry";
|
|
7
7
|
import type { Settings } from "./settings";
|
|
8
8
|
/** Default model IDs for each known provider */
|
|
@@ -204,7 +204,7 @@ export declare function findInitialModel(options: {
|
|
|
204
204
|
isContinuing: boolean;
|
|
205
205
|
defaultProvider?: string;
|
|
206
206
|
defaultModelId?: string;
|
|
207
|
-
defaultThinkingSelector?:
|
|
207
|
+
defaultThinkingSelector?: ThinkingLevel;
|
|
208
208
|
modelRegistry: InitialModelRegistry;
|
|
209
209
|
}): Promise<InitialModelResult>;
|
|
210
210
|
/**
|
|
@@ -907,7 +907,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
907
907
|
};
|
|
908
908
|
readonly defaultThinkingLevel: {
|
|
909
909
|
readonly type: "enum";
|
|
910
|
-
readonly values: readonly Effort[];
|
|
910
|
+
readonly values: readonly ["off", ...Effort[]];
|
|
911
911
|
readonly default: Effort;
|
|
912
912
|
readonly ui: {
|
|
913
913
|
readonly tab: "model";
|
|
@@ -82,6 +82,13 @@ export declare class Settings {
|
|
|
82
82
|
* Call before exit to ensure all changes are persisted.
|
|
83
83
|
*/
|
|
84
84
|
flush(): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Like {@link flush}, but rejects if the durable save fails instead of
|
|
87
|
+
* swallowing the error. Use where the caller must confirm persistence before
|
|
88
|
+
* reporting success (e.g. the Telegram `/rich` toggle). In-memory instances
|
|
89
|
+
* ({@link isolated}) short-circuit in {@link #saveNow} and never throw.
|
|
90
|
+
*/
|
|
91
|
+
flushOrThrow(): Promise<void>;
|
|
85
92
|
cloneForCwd(cwd: string): Promise<Settings>;
|
|
86
93
|
getStorage(): AgentStorage | null;
|
|
87
94
|
getCwd(): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SkillsSettings } from "../config/settings-schema";
|
|
2
|
+
import type { Skill } from "./skills";
|
|
3
|
+
export type RuntimeSkillDiscoverySource = "project" | "user";
|
|
4
|
+
export interface RuntimeSkillDiscoveryCandidate {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
source: RuntimeSkillDiscoverySource;
|
|
8
|
+
path: string;
|
|
9
|
+
useWhen?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface DiscoverRuntimeSkillsOptions {
|
|
12
|
+
cwd: string;
|
|
13
|
+
home?: string;
|
|
14
|
+
query?: string;
|
|
15
|
+
limit?: number;
|
|
16
|
+
source?: RuntimeSkillDiscoverySource | "all";
|
|
17
|
+
policy?: SkillsSettings;
|
|
18
|
+
}
|
|
19
|
+
export declare function discoverRuntimeSkills(options: DiscoverRuntimeSkillsOptions): Promise<RuntimeSkillDiscoveryCandidate[]>;
|
|
20
|
+
export declare function findRuntimeSkillByName(cwd: string, name: string, policy?: SkillsSettings, home?: string): Promise<Skill | undefined>;
|
|
@@ -221,6 +221,7 @@ export interface GjcTeamStartOptions {
|
|
|
221
221
|
cwd?: string;
|
|
222
222
|
env?: NodeJS.ProcessEnv;
|
|
223
223
|
dryRun?: boolean;
|
|
224
|
+
platform?: NodeJS.Platform;
|
|
224
225
|
mailboxDeliveryTransport?: GjcTeamMailboxDeliveryTransport;
|
|
225
226
|
}
|
|
226
227
|
export interface GjcTeamApiClaimResult {
|
|
@@ -305,6 +306,14 @@ export declare function pruneTeamWorkerGcRecord(record: GcRecord, probe: GcPidPr
|
|
|
305
306
|
export declare function persistGjcTeamModeStateSummary(snapshot: GjcTeamSnapshot, cwd?: string): Promise<void>;
|
|
306
307
|
export declare function recoverGjcTeamStaleClaims(teamName: string, cwd?: string, env?: NodeJS.ProcessEnv): Promise<GjcTeamLivenessRecoveryResult>;
|
|
307
308
|
type GjcTeamTaskMetadataInput = Partial<Pick<GjcTeamTask, "owner" | "lane" | "required_role" | "allowed_roles" | "depends_on" | "blocked_by">>;
|
|
309
|
+
export declare function resolveWorkerWorktreePath(input: {
|
|
310
|
+
repoRoot: string;
|
|
311
|
+
stateDir: string;
|
|
312
|
+
teamName: string;
|
|
313
|
+
workerId: string;
|
|
314
|
+
platform: NodeJS.Platform;
|
|
315
|
+
isPsmux: boolean;
|
|
316
|
+
}): string;
|
|
308
317
|
type CommandPathResolver = (command: string) => string | null;
|
|
309
318
|
export declare function resolveGjcWorkerCommand(cwd?: string, env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, argv?: string[], execPath?: string, which?: CommandPathResolver): string;
|
|
310
319
|
/** @internal Exported for unit tests. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ThinkingLevel as ThinkingLevelValue } from "@gajae-code/agent-core";
|
|
2
2
|
import type { Effort } from "@gajae-code/ai";
|
|
3
3
|
import { Container, SettingsList } from "@gajae-code/tui";
|
|
4
4
|
import { type SettingPath } from "../../config/settings";
|
|
@@ -13,7 +13,7 @@ export interface SettingsRuntimeContext {
|
|
|
13
13
|
/** Available thinking levels (from session) */
|
|
14
14
|
availableThinkingLevels: Effort[];
|
|
15
15
|
/** Current thinking level (from session) */
|
|
16
|
-
thinkingLevel:
|
|
16
|
+
thinkingLevel: ThinkingLevelValue | undefined;
|
|
17
17
|
/** Available themes */
|
|
18
18
|
availableThemes: string[];
|
|
19
19
|
/** Available model profile names (from the model registry) */
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { type ThinkingLevel as ThinkingLevelValue } from "@gajae-code/agent-core";
|
|
2
2
|
import { Container, SelectList } from "@gajae-code/tui";
|
|
3
|
+
export interface ThinkingSelectorSelection {
|
|
4
|
+
level: ThinkingLevelValue;
|
|
5
|
+
persistDefault: boolean;
|
|
6
|
+
}
|
|
3
7
|
/**
|
|
4
8
|
* Component that renders a thinking level selector with borders
|
|
5
9
|
*/
|
|
6
10
|
export declare class ThinkingSelectorComponent extends Container {
|
|
7
11
|
#private;
|
|
8
|
-
constructor(currentLevel: ThinkingLevelValue | undefined, availableLevels: ThinkingLevelValue[], onSelect: (
|
|
12
|
+
constructor(currentLevel: ThinkingLevelValue | undefined, availableLevels: ThinkingLevelValue[], onSelect: (selection: ThinkingSelectorSelection) => void, onCancel: () => void);
|
|
13
|
+
handleInput(data: string): void;
|
|
9
14
|
getSelectList(): SelectList;
|
|
10
15
|
}
|
|
@@ -18,6 +18,35 @@ export interface ConfigCommandChange {
|
|
|
18
18
|
verbosity?: "lean" | "verbose";
|
|
19
19
|
redact?: boolean;
|
|
20
20
|
}
|
|
21
|
+
export type TelegramControlCommandName = "reasoning" | "usage" | "context" | "compact";
|
|
22
|
+
export type TelegramControlCommand = {
|
|
23
|
+
name: "reasoning";
|
|
24
|
+
action: "cycle" | "status" | "set";
|
|
25
|
+
level?: string;
|
|
26
|
+
} | {
|
|
27
|
+
name: "usage";
|
|
28
|
+
} | {
|
|
29
|
+
name: "context";
|
|
30
|
+
} | {
|
|
31
|
+
name: "compact";
|
|
32
|
+
instructions?: string;
|
|
33
|
+
};
|
|
34
|
+
export type TelegramControlCommandParseResult = {
|
|
35
|
+
kind: "none";
|
|
36
|
+
} | {
|
|
37
|
+
kind: "ignored";
|
|
38
|
+
commandName: TelegramControlCommandName;
|
|
39
|
+
} | {
|
|
40
|
+
kind: "command";
|
|
41
|
+
command: TelegramControlCommand;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "invalid";
|
|
44
|
+
commandName: TelegramControlCommandName;
|
|
45
|
+
usage: string;
|
|
46
|
+
};
|
|
47
|
+
export declare function telegramControlCommandUsage(commandName: TelegramControlCommandName): string;
|
|
48
|
+
/** Parse deterministic Telegram session-control commands. Recognised roots fail closed. */
|
|
49
|
+
export declare function parseTelegramControlCommand(text: string, botUsername?: string): TelegramControlCommandParseResult;
|
|
21
50
|
/**
|
|
22
51
|
* Parse an in-thread config command. Returns the requested change, or
|
|
23
52
|
* `undefined` when the text is not a recognised config command (so the daemon
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* generated), or `GJC_NOTIFICATIONS_TOKEN`.
|
|
19
19
|
*/
|
|
20
20
|
import { Settings } from "../config/settings";
|
|
21
|
-
import type { ExtensionAPI } from "../extensibility/extensions";
|
|
21
|
+
import type { ExtensionAPI, ExtensionContext } from "../extensibility/extensions";
|
|
22
22
|
/** Where a `session_create` should run. Discriminated by `kind`. */
|
|
23
23
|
export type SessionCreateTarget = {
|
|
24
24
|
kind: "existing_path";
|
|
@@ -176,6 +176,17 @@ export interface SessionReadyFrame {
|
|
|
176
176
|
*/
|
|
177
177
|
export declare function readGitRepoName(cwd: string): string | undefined;
|
|
178
178
|
export declare function notificationsEnabled(): boolean;
|
|
179
|
+
interface NotificationControlCommandPayload {
|
|
180
|
+
name?: unknown;
|
|
181
|
+
action?: unknown;
|
|
182
|
+
level?: unknown;
|
|
183
|
+
instructions?: unknown;
|
|
184
|
+
}
|
|
185
|
+
export declare function executeNotificationControlCommand(command: NotificationControlCommandPayload | undefined, ctx: ExtensionContext, api: ExtensionAPI): Promise<{
|
|
186
|
+
status: "ok" | "error" | "unavailable";
|
|
187
|
+
message: string;
|
|
188
|
+
}>;
|
|
179
189
|
export declare function createNotificationsExtension(api: ExtensionAPI, options?: {
|
|
180
190
|
settings?: Settings;
|
|
181
191
|
}): void;
|
|
192
|
+
export {};
|
|
@@ -9,7 +9,7 @@ export interface RunDaemonInternalDeps {
|
|
|
9
9
|
SettingsImpl?: {
|
|
10
10
|
init: (options?: {
|
|
11
11
|
agentDir?: string;
|
|
12
|
-
}) => Promise<Pick<Settings, "get" | "getAgentDir" | "set">>;
|
|
12
|
+
}) => Promise<Pick<Settings, "get" | "getAgentDir" | "set" | "flush">>;
|
|
13
13
|
};
|
|
14
14
|
DaemonImpl?: TelegramDaemonConstructor;
|
|
15
15
|
processPid?: number;
|
|
@@ -18,8 +18,8 @@ export interface RunDaemonInternalDeps {
|
|
|
18
18
|
export declare function createLightweightDaemonSettings(input: {
|
|
19
19
|
agentDir: string;
|
|
20
20
|
rawConfig?: unknown;
|
|
21
|
-
}): Pick<Settings, "get" | "getAgentDir" | "set">;
|
|
22
|
-
export declare function loadLightweightDaemonSettings(agentDir: string): Promise<Pick<Settings, "get" | "getAgentDir" | "set">>;
|
|
21
|
+
}): Pick<Settings, "get" | "getAgentDir" | "set" | "flush">;
|
|
22
|
+
export declare function loadLightweightDaemonSettings(agentDir: string): Promise<Pick<Settings, "get" | "getAgentDir" | "set" | "flush">>;
|
|
23
23
|
export declare function ownerPidFromOwnerId(ownerId: string): number | undefined;
|
|
24
24
|
export declare function runDaemonSmoke(opts?: {
|
|
25
25
|
agentDir?: string;
|
|
@@ -58,11 +58,10 @@ export declare class TopicRegistry {
|
|
|
58
58
|
markIdentitySent(sessionId: string): void;
|
|
59
59
|
/** Whether the identity header still needs sending for this session. */
|
|
60
60
|
needsIdentity(sessionId: string): boolean;
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
applyName(sessionId: string, name: string): boolean;
|
|
61
|
+
/** Whether a known session topic's applied title differs from `name`. */
|
|
62
|
+
needsRename(sessionId: string, name: string): boolean;
|
|
63
|
+
/** Commit a successfully-applied Telegram topic title. */
|
|
64
|
+
markNameApplied(sessionId: string, name: string): void;
|
|
66
65
|
/** Remove a session topic record after Telegram deletes the topic. */
|
|
67
66
|
delete(sessionId: string): boolean;
|
|
68
67
|
/** Serialise for atomic persistence beside the daemon state. */
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AuthCredentialSelector } from "@gajae-code/ai";
|
|
2
|
+
export interface CliCredentialSelector {
|
|
3
|
+
provider?: string;
|
|
4
|
+
selector: AuthCredentialSelector;
|
|
5
|
+
raw: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseCliCredentialSelector(raw: string): CliCredentialSelector;
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AgentTelemetryConfig, type ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
|
-
import { type Model, type ProviderSessionState } from "@gajae-code/ai";
|
|
2
|
+
import { type AuthCredentialSelector, type Model, type ProviderSessionState } from "@gajae-code/ai";
|
|
3
3
|
import { createAppendOnlyContextManager, providerSupportsAppendOnlyAuto, resolveAppendOnlyMode } from "./append-only-mode";
|
|
4
4
|
import { type Rule } from "./capability/rule";
|
|
5
5
|
import { ModelRegistry } from "./config/model-registry";
|
|
@@ -55,6 +55,12 @@ export interface CreateAgentSessionOptions {
|
|
|
55
55
|
/** Optional provider-facing session identifier for prompt caches and sticky auth selection.
|
|
56
56
|
* Keeps persisted session files isolated while reusing provider-side caches. */
|
|
57
57
|
providerSessionId?: string;
|
|
58
|
+
/** Runtime credential selector for multi-account auth pools. */
|
|
59
|
+
credentialSelector?: {
|
|
60
|
+
provider?: string;
|
|
61
|
+
selector: AuthCredentialSelector;
|
|
62
|
+
raw: string;
|
|
63
|
+
};
|
|
58
64
|
/** Custom tools to register (in addition to built-in tools). Accepts both CustomTool and ToolDefinition. */
|
|
59
65
|
customTools?: (CustomTool | ToolDefinition)[];
|
|
60
66
|
/** Explicit parent/phase used to load active GJC sub-skill tools for this session. */
|
|
@@ -270,6 +270,8 @@ export interface PromptOptions {
|
|
|
270
270
|
images?: ImageContent[];
|
|
271
271
|
/** When streaming, how to queue the message: "steer" (interrupt) or "followUp" (wait). */
|
|
272
272
|
streamingBehavior?: "steer" | "followUp";
|
|
273
|
+
/** When set to "sequential", this follow-up is delivered one prompt at a time even if followUpMode is "all". */
|
|
274
|
+
followUpQueuePolicy?: "respect-mode" | "sequential";
|
|
273
275
|
/** Optional tool choice override for the next LLM call. */
|
|
274
276
|
toolChoice?: ToolChoice;
|
|
275
277
|
/** Send as developer/system message instead of user. Providers that support it use the developer role; others fall back to user. */
|
|
@@ -657,7 +659,7 @@ export declare class AgentSession {
|
|
|
657
659
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
658
660
|
*/
|
|
659
661
|
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>;
|
|
662
|
+
promptCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: Pick<PromptOptions, "streamingBehavior" | "toolChoice" | "followUpQueuePolicy">): Promise<void>;
|
|
661
663
|
/**
|
|
662
664
|
* Queue a steering message to interrupt the agent mid-run.
|
|
663
665
|
*/
|
|
@@ -665,7 +667,7 @@ export declare class AgentSession {
|
|
|
665
667
|
/**
|
|
666
668
|
* Queue a follow-up message to process after the agent would otherwise stop.
|
|
667
669
|
*/
|
|
668
|
-
followUp(text: string, images?: ImageContent[]): Promise<void>;
|
|
670
|
+
followUp(text: string, images?: ImageContent[], options?: Pick<PromptOptions, "followUpQueuePolicy">): Promise<void>;
|
|
669
671
|
queueDeferredMessage(message: CustomMessage): void;
|
|
670
672
|
queueDeferredMessageForTests(message: CustomMessage, triggerTurn?: boolean): void;
|
|
671
673
|
/**
|
|
@@ -679,6 +681,7 @@ export declare class AgentSession {
|
|
|
679
681
|
sendCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: {
|
|
680
682
|
triggerTurn?: boolean;
|
|
681
683
|
deliverAs?: "steer" | "followUp" | "nextTurn";
|
|
684
|
+
followUpQueuePolicy?: "respect-mode" | "sequential";
|
|
682
685
|
}): Promise<void>;
|
|
683
686
|
/** Remove undelivered queued custom messages matching `predicate` from executable queues and tagged display mirrors. */
|
|
684
687
|
purgeQueuedCustomMessages(predicate: (message: CustomMessage) => boolean): PurgeQueuedCustomMessagesResult;
|
|
@@ -834,7 +837,7 @@ export declare class AgentSession {
|
|
|
834
837
|
getAvailableModels(): Model[];
|
|
835
838
|
/**
|
|
836
839
|
* Set thinking level.
|
|
837
|
-
* Saves the effective metadata-clamped level to session and settings
|
|
840
|
+
* Saves the effective metadata-clamped level to the session, and to settings when requested.
|
|
838
841
|
*/
|
|
839
842
|
setThinkingLevel(level: ThinkingLevel | undefined, persist?: boolean): void;
|
|
840
843
|
/**
|
|
@@ -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 {};
|
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.2",
|
|
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.2",
|
|
53
|
+
"@gajae-code/agent-core": "0.9.2",
|
|
54
|
+
"@gajae-code/ai": "0.9.2",
|
|
55
|
+
"@gajae-code/natives": "0.9.2",
|
|
56
|
+
"@gajae-code/tui": "0.9.2",
|
|
57
|
+
"@gajae-code/utils": "0.9.2",
|
|
58
58
|
"@puppeteer/browsers": "^2.13.0",
|
|
59
59
|
"@types/turndown": "5.0.6",
|
|
60
60
|
"@xterm/headless": "^6.0.0",
|
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) {
|