@gajae-code/coding-agent 0.6.4 → 0.7.0
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 +51 -0
- package/dist/types/async/job-manager.d.ts +3 -1
- package/dist/types/cli/daemon-cli.d.ts +25 -0
- package/dist/types/cli/migrate-cli.d.ts +20 -0
- package/dist/types/cli/notify-cli.d.ts +23 -0
- package/dist/types/cli/setup-cli.d.ts +20 -1
- package/dist/types/commands/daemon.d.ts +41 -0
- package/dist/types/commands/migrate.d.ts +33 -0
- package/dist/types/commands/notify.d.ts +41 -0
- package/dist/types/config/keybindings.d.ts +4 -0
- package/dist/types/config/model-profile-activation.d.ts +12 -0
- package/dist/types/config/model-profiles.d.ts +2 -1
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +38 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/daemon/builtin.d.ts +20 -0
- package/dist/types/daemon/control-types.d.ts +57 -0
- package/dist/types/daemon/runtime.d.ts +25 -0
- package/dist/types/extensibility/extensions/types.d.ts +8 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +2 -2
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
- package/dist/types/gjc-runtime/session-layout.d.ts +59 -0
- package/dist/types/gjc-runtime/session-resolution.d.ts +47 -0
- package/dist/types/gjc-runtime/state-graph.d.ts +1 -1
- package/dist/types/gjc-runtime/state-runtime.d.ts +5 -4
- package/dist/types/gjc-runtime/state-schema.d.ts +2 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +38 -7
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +15 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +21 -4
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +1 -1
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +1 -1
- package/dist/types/harness-control-plane/storage.d.ts +2 -1
- package/dist/types/hooks/skill-state.d.ts +12 -4
- package/dist/types/migrate/action-planner.d.ts +11 -0
- package/dist/types/migrate/adapters/claude-code.d.ts +2 -0
- package/dist/types/migrate/adapters/codex.d.ts +5 -0
- package/dist/types/migrate/adapters/index.d.ts +45 -0
- package/dist/types/migrate/adapters/opencode.d.ts +2 -0
- package/dist/types/migrate/executor.d.ts +2 -0
- package/dist/types/migrate/mcp-mapper.d.ts +20 -0
- package/dist/types/migrate/report.d.ts +18 -0
- package/dist/types/migrate/skill-normalizer.d.ts +27 -0
- package/dist/types/migrate/types.d.ts +126 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/oauth-selector.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -2
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +10 -0
- package/dist/types/modes/types.d.ts +7 -1
- package/dist/types/notifications/config-commands.d.ts +26 -0
- package/dist/types/notifications/config.d.ts +61 -0
- package/dist/types/notifications/helpers.d.ts +55 -0
- package/dist/types/notifications/html-format.d.ts +62 -0
- package/dist/types/notifications/index.d.ts +28 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +93 -0
- package/dist/types/notifications/telegram-cli.d.ts +19 -0
- package/dist/types/notifications/telegram-daemon-cli.d.ts +11 -0
- package/dist/types/notifications/telegram-daemon-control.d.ts +56 -0
- package/dist/types/notifications/telegram-daemon.d.ts +276 -0
- package/dist/types/notifications/telegram-reference.d.ts +111 -0
- package/dist/types/notifications/threaded-inbound.d.ts +58 -0
- package/dist/types/notifications/threaded-render.d.ts +66 -0
- package/dist/types/notifications/topic-registry.d.ts +67 -0
- package/dist/types/research-plan/index.d.ts +1 -0
- package/dist/types/research-plan/ledger.d.ts +33 -0
- package/dist/types/rlm/artifacts.d.ts +1 -1
- package/dist/types/rlm/index.d.ts +12 -0
- package/dist/types/runtime-mcp/config-writer.d.ts +26 -0
- package/dist/types/session/agent-session.d.ts +39 -2
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/setup/credential-auto-import.d.ts +63 -0
- package/dist/types/setup/credential-import.d.ts +3 -0
- package/dist/types/setup/host-plugin-setup.d.ts +39 -0
- package/dist/types/skill-state/active-state.d.ts +6 -11
- package/dist/types/skill-state/canonical-skills.d.ts +3 -0
- package/dist/types/skill-state/workflow-hud.d.ts +2 -0
- package/dist/types/task/spawn-gate.d.ts +1 -10
- package/dist/types/tools/ask-answer-registry.d.ts +13 -0
- package/dist/types/tools/index.d.ts +18 -0
- package/dist/types/tools/subagent.d.ts +3 -0
- package/package.json +7 -7
- package/scripts/build-binary.ts +3 -0
- package/src/async/job-manager.ts +5 -1
- package/src/cli/daemon-cli.ts +122 -0
- package/src/cli/migrate-cli.ts +106 -0
- package/src/cli/notify-cli.ts +274 -0
- package/src/cli/setup-cli.ts +173 -84
- package/src/cli.ts +3 -0
- package/src/commands/daemon.ts +47 -0
- package/src/commands/deep-interview.ts +2 -2
- package/src/commands/migrate.ts +46 -0
- package/src/commands/notify.ts +61 -0
- package/src/commands/setup.ts +11 -1
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +7 -3
- package/src/config/model-profile-activation.ts +74 -5
- package/src/config/model-profiles.ts +7 -4
- package/src/config/model-registry.ts +6 -3
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +29 -0
- package/src/coordinator/contract.ts +3 -0
- package/src/coordinator-mcp/policy.ts +10 -2
- package/src/coordinator-mcp/server.ts +270 -1
- package/src/daemon/builtin.ts +46 -0
- package/src/daemon/control-types.ts +65 -0
- package/src/daemon/runtime.ts +51 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +0 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +28 -24
- package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -4
- package/src/defaults/gjc/skills/team/SKILL.md +51 -47
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +33 -13
- package/src/extensibility/custom-commands/loader.ts +0 -7
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +8 -0
- package/src/extensibility/gjc-plugins/injection.ts +23 -4
- package/src/extensibility/gjc-plugins/state.ts +16 -1
- package/src/gjc-runtime/deep-interview-recorder.ts +51 -18
- package/src/gjc-runtime/deep-interview-runtime.ts +49 -23
- package/src/gjc-runtime/goal-mode-request.ts +26 -11
- package/src/gjc-runtime/launch-tmux.ts +6 -1
- package/src/gjc-runtime/ralplan-runtime.ts +79 -50
- package/src/gjc-runtime/session-layout.ts +180 -0
- package/src/gjc-runtime/session-resolution.ts +217 -0
- package/src/gjc-runtime/state-graph.ts +1 -2
- package/src/gjc-runtime/state-migrations.ts +1 -0
- package/src/gjc-runtime/state-runtime.ts +247 -124
- package/src/gjc-runtime/state-schema.ts +2 -0
- package/src/gjc-runtime/state-writer.ts +289 -41
- package/src/gjc-runtime/team-runtime.ts +43 -19
- package/src/gjc-runtime/tmux-sessions.ts +7 -1
- package/src/gjc-runtime/ultragoal-guard.ts +102 -4
- package/src/gjc-runtime/ultragoal-runtime.ts +226 -60
- package/src/gjc-runtime/workflow-command-ref.ts +1 -2
- package/src/gjc-runtime/workflow-manifest.generated.json +27 -2
- package/src/gjc-runtime/workflow-manifest.ts +12 -3
- package/src/goals/tools/goal-tool.ts +11 -2
- package/src/harness-control-plane/storage.ts +14 -4
- package/src/hooks/native-skill-hook.ts +38 -12
- package/src/hooks/skill-state.ts +178 -83
- package/src/internal-urls/docs-index.generated.ts +9 -6
- package/src/main.ts +30 -0
- package/src/migrate/action-planner.ts +318 -0
- package/src/migrate/adapters/claude-code.ts +39 -0
- package/src/migrate/adapters/codex.ts +70 -0
- package/src/migrate/adapters/index.ts +277 -0
- package/src/migrate/adapters/opencode.ts +52 -0
- package/src/migrate/executor.ts +81 -0
- package/src/migrate/mcp-mapper.ts +152 -0
- package/src/migrate/report.ts +104 -0
- package/src/migrate/skill-normalizer.ts +80 -0
- package/src/migrate/types.ts +163 -0
- package/src/modes/acp/acp-event-mapper.ts +1 -0
- package/src/modes/bridge/bridge-mode.ts +2 -2
- package/src/modes/components/custom-editor.ts +30 -20
- package/src/modes/components/hook-editor.ts +7 -2
- package/src/modes/components/oauth-selector.ts +19 -0
- package/src/modes/controllers/event-controller.ts +20 -0
- package/src/modes/controllers/selector-controller.ts +80 -17
- package/src/modes/interactive-mode.ts +6 -2
- package/src/modes/rpc/rpc-mode.ts +2 -2
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/shared/agent-wire/event-contract.ts +1 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +1 -0
- package/src/modes/shared/agent-wire/event-observation.ts +16 -0
- package/src/modes/shared/agent-wire/unattended-audit.ts +3 -2
- package/src/modes/shared/agent-wire/unattended-session.ts +22 -0
- package/src/modes/types.ts +7 -1
- package/src/modes/utils/ui-helpers.ts +23 -0
- package/src/notifications/config-commands.ts +50 -0
- package/src/notifications/config.ts +107 -0
- package/src/notifications/helpers.ts +135 -0
- package/src/notifications/html-format.ts +389 -0
- package/src/notifications/index.ts +663 -0
- package/src/notifications/rate-limit-pool.ts +179 -0
- package/src/notifications/telegram-cli.ts +194 -0
- package/src/notifications/telegram-daemon-cli.ts +74 -0
- package/src/notifications/telegram-daemon-control.ts +370 -0
- package/src/notifications/telegram-daemon.ts +1370 -0
- package/src/notifications/telegram-reference.ts +335 -0
- package/src/notifications/threaded-inbound.ts +80 -0
- package/src/notifications/threaded-render.ts +155 -0
- package/src/notifications/topic-registry.ts +133 -0
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/system/plan-mode-active.md +1 -1
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/task.md +1 -2
- package/src/research-plan/index.ts +1 -0
- package/src/research-plan/ledger.ts +177 -0
- package/src/rlm/artifacts.ts +12 -3
- package/src/rlm/index.ts +26 -0
- package/src/runtime-mcp/config-writer.ts +46 -0
- package/src/sdk.ts +16 -0
- package/src/session/agent-session.ts +128 -24
- package/src/session/auth-storage.ts +3 -0
- package/src/session/session-dump-format.ts +43 -2
- package/src/session/session-manager.ts +39 -5
- package/src/setup/credential-auto-import.ts +258 -0
- package/src/setup/credential-import.ts +17 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +10 -0
- package/src/setup/hermes-setup.ts +1 -1
- package/src/setup/host-plugin-setup.ts +142 -0
- package/src/skill-state/active-state.ts +72 -108
- package/src/skill-state/canonical-skills.ts +4 -0
- package/src/skill-state/deep-interview-mutation-guard.ts +28 -109
- package/src/skill-state/workflow-hud.ts +4 -2
- package/src/skill-state/workflow-state-contract.ts +3 -3
- package/src/slash-commands/builtin-registry.ts +4 -1
- package/src/task/agents.ts +1 -22
- package/src/task/executor.ts +5 -1
- package/src/task/index.ts +1 -41
- package/src/task/spawn-gate.ts +1 -38
- package/src/task/types.ts +1 -1
- package/src/tools/ask-answer-registry.ts +25 -0
- package/src/tools/ask.ts +108 -16
- package/src/tools/computer.ts +58 -4
- package/src/tools/image-gen.ts +5 -8
- package/src/tools/index.ts +19 -0
- package/src/tools/inspect-image.ts +16 -11
- package/src/tools/subagent-render.ts +7 -0
- package/src/tools/subagent.ts +38 -7
- package/dist/types/extensibility/custom-commands/bundled/review/index.d.ts +0 -10
- package/src/extensibility/custom-commands/bundled/review/index.ts +0 -456
- package/src/prompts/agents/explore.md +0 -58
- package/src/prompts/agents/plan.md +0 -49
- package/src/prompts/agents/reviewer.md +0 -141
- package/src/prompts/agents/task.md +0 -16
- package/src/prompts/review-request.md +0 -70
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a skill from another agent into a native GJC `SKILL.md`.
|
|
3
|
+
*
|
|
4
|
+
* GJC derives a skill's loaded name from its directory (`<slug>/SKILL.md`) when no
|
|
5
|
+
* frontmatter `name` is present, and requires a `description`. To guarantee the
|
|
6
|
+
* effective loaded name equals the lowercase-hyphen slug, we drop any frontmatter
|
|
7
|
+
* `name` and place the file at `<slug>/SKILL.md`, synthesizing a `description`
|
|
8
|
+
* when the source lacks one.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { parseFrontmatter } from "@gajae-code/utils";
|
|
12
|
+
import { YAML } from "bun";
|
|
13
|
+
|
|
14
|
+
export interface NormalizeSkillInput {
|
|
15
|
+
/** Raw name from the source (filename stem, frontmatter name, etc.). */
|
|
16
|
+
rawName: string;
|
|
17
|
+
/** Full source markdown (may or may not have frontmatter). */
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NormalizedSkill {
|
|
22
|
+
slug: string;
|
|
23
|
+
content: string;
|
|
24
|
+
warnings: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Convert an arbitrary name into a lowercase-hyphen slug. */
|
|
28
|
+
export function slugify(name: string): string {
|
|
29
|
+
const slug = name
|
|
30
|
+
.normalize("NFKD")
|
|
31
|
+
.replace(/[^\w\s-]/g, "")
|
|
32
|
+
.trim()
|
|
33
|
+
.toLowerCase()
|
|
34
|
+
.replace(/[\s_]+/g, "-")
|
|
35
|
+
.replace(/-+/g, "-")
|
|
36
|
+
.replace(/^-+|-+$/g, "");
|
|
37
|
+
return slug;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function firstNonEmptyLine(body: string): string | undefined {
|
|
41
|
+
for (const raw of body.split("\n")) {
|
|
42
|
+
const line = raw.replace(/^#+\s*/, "").trim();
|
|
43
|
+
if (line) return line;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Produce a `{ slug, content }` pair whose effective GJC-loaded name equals `slug`.
|
|
50
|
+
* Throws only on an unusable name (cannot produce a slug).
|
|
51
|
+
*/
|
|
52
|
+
export function normalizeSkill(input: NormalizeSkillInput): NormalizedSkill {
|
|
53
|
+
const warnings: string[] = [];
|
|
54
|
+
const { frontmatter, body } = parseFrontmatter(input.content, { level: "off" });
|
|
55
|
+
|
|
56
|
+
const sourceName =
|
|
57
|
+
typeof frontmatter.name === "string" && frontmatter.name.trim() ? frontmatter.name : input.rawName;
|
|
58
|
+
const slug = slugify(sourceName);
|
|
59
|
+
if (!slug) {
|
|
60
|
+
throw new Error(`cannot derive a valid slug from skill name "${input.rawName}"`);
|
|
61
|
+
}
|
|
62
|
+
if (slugify(input.rawName) !== slug && typeof frontmatter.name === "string") {
|
|
63
|
+
warnings.push(`renamed skill "${input.rawName}" to slug "${slug}"`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Build the destination frontmatter: drop `name` (loaded name comes from the dir),
|
|
67
|
+
// keep other fields, and ensure a non-empty description.
|
|
68
|
+
const { name: _droppedName, description: rawDescription, ...rest } = frontmatter;
|
|
69
|
+
let description = typeof rawDescription === "string" ? rawDescription.trim() : "";
|
|
70
|
+
if (!description) {
|
|
71
|
+
description = firstNonEmptyLine(body) ?? `Imported ${slug} skill.`;
|
|
72
|
+
warnings.push(`synthesized description for skill "${slug}"`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const fm: Record<string, unknown> = { description, ...rest };
|
|
76
|
+
const yaml = YAML.stringify(fm).trimEnd();
|
|
77
|
+
const content = `---\n${yaml}\n---\n\n${body.trim()}\n`;
|
|
78
|
+
|
|
79
|
+
return { slug, content, warnings };
|
|
80
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for `gjc migrate`.
|
|
3
|
+
*
|
|
4
|
+
* Imports MCP servers and skills from other coding agents (Claude Code, Codex,
|
|
5
|
+
* OpenCode) into native GJC config. See the consensus plan under
|
|
6
|
+
* `.gjc/plans/ralplan/` for the full taxonomy and force/collision semantics.
|
|
7
|
+
*/
|
|
8
|
+
import type { MCPServerConfig } from "../runtime-mcp/types";
|
|
9
|
+
|
|
10
|
+
/** Supported migration sources. */
|
|
11
|
+
export type MigrateSource = "claude-code" | "codex" | "opencode";
|
|
12
|
+
|
|
13
|
+
export const MIGRATE_SOURCES: readonly MigrateSource[] = ["claude-code", "codex", "opencode"];
|
|
14
|
+
|
|
15
|
+
/** Canonical, deterministic ordering used when expanding `--from all` / repeated `--from`. */
|
|
16
|
+
export const CANONICAL_SOURCE_ORDER: readonly MigrateSource[] = MIGRATE_SOURCES;
|
|
17
|
+
|
|
18
|
+
/** What kind of thing an action/coverage row is about. */
|
|
19
|
+
export type MigrateItemType = "mcp" | "skill" | "source";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Per-item outcome taxonomy.
|
|
23
|
+
*
|
|
24
|
+
* `skipped_*` outcomes are non-fatal (exit 0). Any `failed_*` outcome sets
|
|
25
|
+
* `ok=false` and a non-zero process exit code.
|
|
26
|
+
*/
|
|
27
|
+
export type MigrationStatus =
|
|
28
|
+
| "imported"
|
|
29
|
+
| "updated"
|
|
30
|
+
| "skipped_exists"
|
|
31
|
+
| "skipped_absent_source"
|
|
32
|
+
| "skipped_unmappable"
|
|
33
|
+
| "failed_invalid_source"
|
|
34
|
+
| "failed_invalid_destination"
|
|
35
|
+
| "failed_io";
|
|
36
|
+
|
|
37
|
+
export const MIGRATION_STATUSES: readonly MigrationStatus[] = [
|
|
38
|
+
"imported",
|
|
39
|
+
"updated",
|
|
40
|
+
"skipped_exists",
|
|
41
|
+
"skipped_absent_source",
|
|
42
|
+
"skipped_unmappable",
|
|
43
|
+
"failed_invalid_source",
|
|
44
|
+
"failed_invalid_destination",
|
|
45
|
+
"failed_io",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/** Statuses that represent a hard failure (drive `ok=false` + non-zero exit). */
|
|
49
|
+
export const FAILURE_STATUSES: ReadonlySet<MigrationStatus> = new Set<MigrationStatus>([
|
|
50
|
+
"failed_invalid_source",
|
|
51
|
+
"failed_invalid_destination",
|
|
52
|
+
"failed_io",
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
export function isFailureStatus(status: MigrationStatus): boolean {
|
|
56
|
+
return FAILURE_STATUSES.has(status);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Operation the planner decided for an item. */
|
|
60
|
+
export type MigrateOperation = "create" | "update" | "skip" | "fail";
|
|
61
|
+
|
|
62
|
+
/** A raw MCP server candidate parsed from a source, before mapping/destination planning. */
|
|
63
|
+
export interface McpCandidate {
|
|
64
|
+
source: MigrateSource;
|
|
65
|
+
name: string;
|
|
66
|
+
/** The raw, unmapped server entry from the source config (mapped by the planner). */
|
|
67
|
+
raw: unknown;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** A raw skill candidate parsed from a source, before normalization/destination planning. */
|
|
71
|
+
export interface SkillCandidate {
|
|
72
|
+
source: MigrateSource;
|
|
73
|
+
/** Slug used as the destination directory and effective loaded name. */
|
|
74
|
+
slug: string;
|
|
75
|
+
/** Full SKILL.md content (frontmatter already normalized so loaded name == slug). */
|
|
76
|
+
content: string;
|
|
77
|
+
warnings: string[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Source-level diagnostic for a single source/type pair (e.g. "codex mcp config
|
|
82
|
+
* was malformed"). Distinct from per-item actions so absent/unreadable sources
|
|
83
|
+
* are reported once instead of per item.
|
|
84
|
+
*/
|
|
85
|
+
export interface SourceDiagnostic {
|
|
86
|
+
source: MigrateSource;
|
|
87
|
+
type: Exclude<MigrateItemType, "source"> | "source";
|
|
88
|
+
status: Extract<MigrationStatus, "skipped_absent_source" | "failed_invalid_source" | "failed_io">;
|
|
89
|
+
message: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Normalized candidates + diagnostics returned by an adapter. */
|
|
93
|
+
export interface AdapterResult {
|
|
94
|
+
mcpCandidates: McpCandidate[];
|
|
95
|
+
skillCandidates: SkillCandidate[];
|
|
96
|
+
diagnostics: SourceDiagnostic[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A single planned action consumed identically by dry-run and live execution. */
|
|
100
|
+
export interface MigrateAction {
|
|
101
|
+
source: MigrateSource;
|
|
102
|
+
type: MigrateItemType;
|
|
103
|
+
name?: string;
|
|
104
|
+
/** For skills: the effective GJC-loaded name (== slug). */
|
|
105
|
+
effectiveName?: string;
|
|
106
|
+
/** Absolute destination path (mcp.json for MCP, <skillsDir>/<slug>/SKILL.md for skills). */
|
|
107
|
+
destination?: string;
|
|
108
|
+
operation: MigrateOperation;
|
|
109
|
+
status: MigrationStatus;
|
|
110
|
+
reason?: string;
|
|
111
|
+
warnings?: string[];
|
|
112
|
+
/** Resolved payload the executor needs; never serialized to the report. */
|
|
113
|
+
mcp?: { config: MCPServerConfig; force: boolean };
|
|
114
|
+
skill?: { content: string };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface MigrateWarning {
|
|
118
|
+
source: MigrateSource;
|
|
119
|
+
type: string;
|
|
120
|
+
name?: string;
|
|
121
|
+
message: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type StatusCounts = Record<MigrationStatus, number>;
|
|
125
|
+
|
|
126
|
+
export interface MigrateDestinations {
|
|
127
|
+
mcpConfigPath: string;
|
|
128
|
+
skillsDir: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** The full machine-readable report emitted with `--json`. */
|
|
132
|
+
export interface MigrateReport {
|
|
133
|
+
ok: boolean;
|
|
134
|
+
dryRun: boolean;
|
|
135
|
+
project: boolean;
|
|
136
|
+
force: boolean;
|
|
137
|
+
sources: MigrateSource[];
|
|
138
|
+
destinations: MigrateDestinations;
|
|
139
|
+
summary: {
|
|
140
|
+
total: StatusCounts;
|
|
141
|
+
byType: { mcp: StatusCounts; skill: StatusCounts; source: StatusCounts };
|
|
142
|
+
bySource: Record<MigrateSource, StatusCounts>;
|
|
143
|
+
};
|
|
144
|
+
actions: Array<{
|
|
145
|
+
source: MigrateSource;
|
|
146
|
+
type: MigrateItemType;
|
|
147
|
+
name?: string;
|
|
148
|
+
effectiveName?: string;
|
|
149
|
+
destination?: string;
|
|
150
|
+
operation: MigrateOperation;
|
|
151
|
+
status: MigrationStatus;
|
|
152
|
+
reason?: string;
|
|
153
|
+
warnings?: string[];
|
|
154
|
+
}>;
|
|
155
|
+
warnings: MigrateWarning[];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Create a zeroed status-count record. */
|
|
159
|
+
export function emptyStatusCounts(): StatusCounts {
|
|
160
|
+
const counts = {} as StatusCounts;
|
|
161
|
+
for (const status of MIGRATION_STATUSES) counts[status] = 0;
|
|
162
|
+
return counts;
|
|
163
|
+
}
|
|
@@ -244,6 +244,7 @@ export function mapAgentSessionEventToAcpSessionUpdates(
|
|
|
244
244
|
case "retry_fallback_succeeded":
|
|
245
245
|
case "ttsr_triggered":
|
|
246
246
|
case "irc_message":
|
|
247
|
+
case "subagent_steer_message":
|
|
247
248
|
case "notice":
|
|
248
249
|
case "thinking_level_changed":
|
|
249
250
|
case "goal_updated":
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
1
|
import type { ExtensionUIContext } from "../../extensibility/extensions";
|
|
2
|
+
import { workflowGatePath } from "../../gjc-runtime/session-layout";
|
|
3
3
|
import type { AgentSession } from "../../session/agent-session";
|
|
4
4
|
import type { ClientBridgePermissionOutcome } from "../../session/client-bridge";
|
|
5
5
|
import type { RpcCommand, RpcResponse, RpcWorkflowGateResponse } from "../rpc/rpc-types";
|
|
@@ -611,7 +611,7 @@ export async function runBridgeMode(
|
|
|
611
611
|
});
|
|
612
612
|
};
|
|
613
613
|
const gateStore = new FileGateStore(
|
|
614
|
-
|
|
614
|
+
workflowGatePath(session.sessionManager.getCwd(), session.sessionId, session.sessionId),
|
|
615
615
|
);
|
|
616
616
|
const unattendedControlPlane = new UnattendedSessionControlPlane({
|
|
617
617
|
runId: session.sessionId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Editor, type KeyId, matchesKey, parseKittySequence } from "@gajae-code/tui";
|
|
2
2
|
import { BracketedPasteHandler } from "@gajae-code/tui/bracketed-paste";
|
|
3
|
-
import type
|
|
3
|
+
import { type AppKeybinding, KEYBINDINGS } from "../../config/keybindings";
|
|
4
4
|
|
|
5
5
|
type ConfigurableEditorAction = Extract<
|
|
6
6
|
AppKeybinding,
|
|
@@ -23,25 +23,35 @@ type ConfigurableEditorAction = Extract<
|
|
|
23
23
|
| "app.clipboard.copyPrompt"
|
|
24
24
|
>;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"app.
|
|
31
|
-
"app.
|
|
32
|
-
"app.
|
|
33
|
-
"app.
|
|
34
|
-
"app.
|
|
35
|
-
"app.model.
|
|
36
|
-
"app.
|
|
37
|
-
"app.
|
|
38
|
-
"app.
|
|
39
|
-
"app.
|
|
40
|
-
"app.
|
|
41
|
-
"app.
|
|
42
|
-
"app.
|
|
43
|
-
"app.
|
|
44
|
-
|
|
26
|
+
// Editor-configurable app actions. Defaults are derived from the central
|
|
27
|
+
// KEYBINDINGS registry so there is a single source of truth (e.g. the
|
|
28
|
+
// platform-aware app.clipboard.pasteImage default is not duplicated here).
|
|
29
|
+
const CONFIGURABLE_EDITOR_ACTIONS = [
|
|
30
|
+
"app.interrupt",
|
|
31
|
+
"app.clear",
|
|
32
|
+
"app.exit",
|
|
33
|
+
"app.suspend",
|
|
34
|
+
"app.thinking.cycle",
|
|
35
|
+
"app.model.cycleForward",
|
|
36
|
+
"app.model.cycleBackward",
|
|
37
|
+
"app.model.select",
|
|
38
|
+
"app.model.selectTemporary",
|
|
39
|
+
"app.tools.expand",
|
|
40
|
+
"app.thinking.toggle",
|
|
41
|
+
"app.editor.external",
|
|
42
|
+
"app.history.search",
|
|
43
|
+
"app.message.queue",
|
|
44
|
+
"app.message.dequeue",
|
|
45
|
+
"app.clipboard.pasteImage",
|
|
46
|
+
"app.clipboard.copyPrompt",
|
|
47
|
+
] as const satisfies readonly ConfigurableEditorAction[];
|
|
48
|
+
|
|
49
|
+
const DEFAULT_ACTION_KEYS = Object.fromEntries(
|
|
50
|
+
CONFIGURABLE_EDITOR_ACTIONS.map(action => {
|
|
51
|
+
const defaultKeys = KEYBINDINGS[action].defaultKeys;
|
|
52
|
+
return [action, Array.isArray(defaultKeys) ? [...defaultKeys] : [defaultKeys]];
|
|
53
|
+
}),
|
|
54
|
+
) as Record<ConfigurableEditorAction, KeyId[]>;
|
|
45
55
|
|
|
46
56
|
const PASTE_DECISION_TIMEOUT_MS = 5_000;
|
|
47
57
|
const PENDING_PASTE_INPUT_MAX = 64;
|
|
@@ -17,6 +17,10 @@ export interface HookEditorOptions {
|
|
|
17
17
|
promptStyle?: boolean;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function isWindowsRawLfNewlineInput(keyData: string): boolean {
|
|
21
|
+
return process.platform === "win32" && keyData === "\n";
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
export class HookEditorComponent extends Container {
|
|
21
25
|
#editor: Editor;
|
|
22
26
|
#onSubmitCallback: (value: string) => void;
|
|
@@ -92,8 +96,9 @@ export class HookEditorComponent extends Container {
|
|
|
92
96
|
return;
|
|
93
97
|
}
|
|
94
98
|
|
|
95
|
-
// Submit on
|
|
96
|
-
|
|
99
|
+
// Submit on plain Enter encodings. On Windows, raw LF is reserved for terminal
|
|
100
|
+
// newline mappings (Shift+Enter/Ctrl+J/Ctrl+Enter); plain Enter reports CR.
|
|
101
|
+
if (!isWindowsRawLfNewlineInput(keyData) && (matchesKey(keyData, "enter") || matchesKey(keyData, "return"))) {
|
|
97
102
|
this.#onSubmitCallback(this.#editor.getText());
|
|
98
103
|
return;
|
|
99
104
|
}
|
|
@@ -4,6 +4,7 @@ import { Container, matchesKey, Spacer, TruncatedText } from "@gajae-code/tui";
|
|
|
4
4
|
import { theme } from "../../modes/theme/theme";
|
|
5
5
|
import { matchesSelectCancel } from "../../modes/utils/keybinding-matchers";
|
|
6
6
|
import type { AuthStorage } from "../../session/auth-storage";
|
|
7
|
+
import type { ImportableCredential } from "../../setup/credential-import";
|
|
7
8
|
import { DynamicBorder } from "./dynamic-border";
|
|
8
9
|
|
|
9
10
|
const OAUTH_SELECTOR_MAX_VISIBLE = 10;
|
|
@@ -22,6 +23,7 @@ export class OAuthSelectorComponent extends Container {
|
|
|
22
23
|
#validateAuthCallback?: (providerId: string) => Promise<boolean>;
|
|
23
24
|
#requestRenderCallback?: () => void;
|
|
24
25
|
#authState: Map<string, "checking" | "valid" | "invalid"> = new Map();
|
|
26
|
+
#externalCredentialCandidates: ImportableCredential[] = [];
|
|
25
27
|
#spinnerFrame: number = 0;
|
|
26
28
|
#spinnerInterval?: NodeJS.Timeout;
|
|
27
29
|
#validationGeneration: number = 0;
|
|
@@ -33,6 +35,7 @@ export class OAuthSelectorComponent extends Container {
|
|
|
33
35
|
options?: {
|
|
34
36
|
validateAuth?: (providerId: string) => Promise<boolean>;
|
|
35
37
|
requestRender?: () => void;
|
|
38
|
+
externalCredentialCandidates?: ImportableCredential[];
|
|
36
39
|
},
|
|
37
40
|
) {
|
|
38
41
|
super();
|
|
@@ -42,6 +45,7 @@ export class OAuthSelectorComponent extends Container {
|
|
|
42
45
|
this.#onCancelCallback = onCancel;
|
|
43
46
|
this.#validateAuthCallback = options?.validateAuth;
|
|
44
47
|
this.#requestRenderCallback = options?.requestRender;
|
|
48
|
+
this.#externalCredentialCandidates = options?.externalCredentialCandidates ?? [];
|
|
45
49
|
// Load all OAuth providers
|
|
46
50
|
this.#loadProviders();
|
|
47
51
|
this.addChild(new DynamicBorder());
|
|
@@ -195,6 +199,21 @@ export class OAuthSelectorComponent extends Container {
|
|
|
195
199
|
this.#listContainer.addChild(new Spacer(1));
|
|
196
200
|
this.#listContainer.addChild(new TruncatedText(theme.fg("warning", ` ${this.#statusMessage}`), 0, 0));
|
|
197
201
|
}
|
|
202
|
+
if (this.#mode === "login" && this.#externalCredentialCandidates.length > 0) {
|
|
203
|
+
this.#listContainer.addChild(new Spacer(1));
|
|
204
|
+
for (const credential of this.#externalCredentialCandidates) {
|
|
205
|
+
this.#listContainer.addChild(
|
|
206
|
+
new TruncatedText(
|
|
207
|
+
theme.fg(
|
|
208
|
+
"success",
|
|
209
|
+
` ${theme.status.success} Imported ${credential.provider} from ${credential.source}`,
|
|
210
|
+
),
|
|
211
|
+
0,
|
|
212
|
+
0,
|
|
213
|
+
),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
198
217
|
}
|
|
199
218
|
handleInput(keyData: string): void {
|
|
200
219
|
// Up arrow
|
|
@@ -83,6 +83,7 @@ export class EventController {
|
|
|
83
83
|
todo_reminder: e => this.#handleTodoReminder(e),
|
|
84
84
|
todo_auto_clear: e => this.#handleTodoAutoClear(e),
|
|
85
85
|
irc_message: e => this.#handleIrcMessage(e),
|
|
86
|
+
subagent_steer_message: e => this.#handleSubagentSteerMessage(e),
|
|
86
87
|
notice: e => this.#handleNotice(e),
|
|
87
88
|
thinking_level_changed: async () => {},
|
|
88
89
|
goal_updated: async () => {},
|
|
@@ -284,6 +285,25 @@ export class EventController {
|
|
|
284
285
|
this.ctx.ui.requestRender();
|
|
285
286
|
}
|
|
286
287
|
|
|
288
|
+
async #handleSubagentSteerMessage(
|
|
289
|
+
event: Extract<AgentSessionEvent, { type: "subagent_steer_message" }>,
|
|
290
|
+
): Promise<void> {
|
|
291
|
+
const details = event.message.details as
|
|
292
|
+
| { observationId?: string; from?: string; to?: string; body?: string; state?: string }
|
|
293
|
+
| undefined;
|
|
294
|
+
const obsId = details?.observationId;
|
|
295
|
+
const signature = obsId
|
|
296
|
+
? `steer:${obsId}`
|
|
297
|
+
: `${event.message.role}:${event.message.customType}:${event.message.timestamp}:${details?.from}:${details?.to}:${details?.state}:${details?.body}`;
|
|
298
|
+
if (this.#renderedCustomMessages.has(signature)) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
this.#renderedCustomMessages.add(signature);
|
|
302
|
+
this.#resetReadGroup();
|
|
303
|
+
this.ctx.addMessageToChat(event.message);
|
|
304
|
+
this.ctx.ui.requestRender();
|
|
305
|
+
}
|
|
306
|
+
|
|
287
307
|
#scheduleIrcExpiry(signature: string, components: Component[]): void {
|
|
288
308
|
if (components.length === 0 || this.#ircExpiryTimers.has(signature)) return;
|
|
289
309
|
const timer = setTimeout(() => {
|
|
@@ -29,10 +29,14 @@ import {
|
|
|
29
29
|
setTheme,
|
|
30
30
|
theme,
|
|
31
31
|
} from "../../modes/theme/theme";
|
|
32
|
-
import type { InteractiveModeContext } from "../../modes/types";
|
|
32
|
+
import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/types";
|
|
33
33
|
import { type SessionInfo, SessionManager } from "../../session/session-manager";
|
|
34
34
|
import { FileSessionStorage } from "../../session/session-storage";
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING,
|
|
37
|
+
runExternalCredentialAutoImport,
|
|
38
|
+
} from "../../setup/credential-auto-import";
|
|
39
|
+
import { filterAutoImportOAuthCredentials, formatDiscoverySummary } from "../../setup/credential-import";
|
|
36
40
|
import {
|
|
37
41
|
MODEL_ONBOARDING_API_PROVIDER_COMMAND,
|
|
38
42
|
MODEL_ONBOARDING_PROVIDER_PRESET_COMMAND,
|
|
@@ -156,10 +160,22 @@ export class SelectorController {
|
|
|
156
160
|
|
|
157
161
|
async #handleCredentialImport(): Promise<void> {
|
|
158
162
|
this.ctx.showStatus("Scanning for existing Claude Code / Codex CLI credentials…");
|
|
159
|
-
const
|
|
160
|
-
|
|
163
|
+
const preview = await runExternalCredentialAutoImport({
|
|
164
|
+
authStorage: {
|
|
165
|
+
importCredentialIfAbsent: async () => ({
|
|
166
|
+
inserted: false,
|
|
167
|
+
reason: "skipped-existing",
|
|
168
|
+
provider: "",
|
|
169
|
+
entries: [],
|
|
170
|
+
}),
|
|
171
|
+
},
|
|
172
|
+
trigger: "bare-login",
|
|
173
|
+
});
|
|
174
|
+
const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
175
|
+
const candidates = filterAutoImportOAuthCredentials(result.importable);
|
|
176
|
+
const summaryLines = formatDiscoverySummary({ ...result, importable: candidates });
|
|
161
177
|
|
|
162
|
-
if (
|
|
178
|
+
if (candidates.length === 0) {
|
|
163
179
|
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
164
180
|
for (const line of summaryLines) {
|
|
165
181
|
this.ctx.chatContainer.addChild(new Text(theme.fg("dim", line), 1, 0));
|
|
@@ -168,7 +184,7 @@ export class SelectorController {
|
|
|
168
184
|
new Text(
|
|
169
185
|
theme.fg(
|
|
170
186
|
"warning",
|
|
171
|
-
"No importable Claude/Codex credentials found. Use /login or add a custom provider.",
|
|
187
|
+
"No importable Claude/Codex OAuth credentials found. Use /login or add a custom provider.",
|
|
172
188
|
),
|
|
173
189
|
1,
|
|
174
190
|
0,
|
|
@@ -179,7 +195,7 @@ export class SelectorController {
|
|
|
179
195
|
}
|
|
180
196
|
|
|
181
197
|
const confirmed = await this.ctx.showHookConfirm(
|
|
182
|
-
`Import ${
|
|
198
|
+
`Import ${candidates.length} credential(s)?`,
|
|
183
199
|
summaryLines.join("\n"),
|
|
184
200
|
);
|
|
185
201
|
if (!confirmed) {
|
|
@@ -187,9 +203,10 @@ export class SelectorController {
|
|
|
187
203
|
return;
|
|
188
204
|
}
|
|
189
205
|
|
|
190
|
-
const summary = await
|
|
191
|
-
this.ctx.session.modelRegistry.authStorage
|
|
192
|
-
|
|
206
|
+
const summary = await runExternalCredentialAutoImport({
|
|
207
|
+
authStorage: this.ctx.session.modelRegistry.authStorage,
|
|
208
|
+
trigger: "bare-login",
|
|
209
|
+
});
|
|
193
210
|
await this.ctx.session.modelRegistry.refresh();
|
|
194
211
|
|
|
195
212
|
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
@@ -202,13 +219,15 @@ export class SelectorController {
|
|
|
202
219
|
),
|
|
203
220
|
);
|
|
204
221
|
}
|
|
205
|
-
for (const
|
|
222
|
+
for (const skip of summary.skipped) {
|
|
206
223
|
this.ctx.chatContainer.addChild(
|
|
207
|
-
new Text(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
224
|
+
new Text(theme.fg("dim", `${theme.status.info} Skipped ${skip.credential.provider}: ${skip.reason}`), 1, 0),
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
for (const failure of summary.failures) {
|
|
228
|
+
const provider = failure.credential?.provider ?? failure.origin ?? "credential discovery";
|
|
229
|
+
this.ctx.chatContainer.addChild(
|
|
230
|
+
new Text(theme.fg("error", `${theme.status.error} Failed ${provider}: ${failure.failureClass}`), 1, 0),
|
|
212
231
|
);
|
|
213
232
|
}
|
|
214
233
|
if (summary.imported.length > 0) {
|
|
@@ -1232,7 +1251,11 @@ export class SelectorController {
|
|
|
1232
1251
|
}
|
|
1233
1252
|
}
|
|
1234
1253
|
|
|
1235
|
-
async showOAuthSelector(
|
|
1254
|
+
async showOAuthSelector(
|
|
1255
|
+
mode: "login" | "logout",
|
|
1256
|
+
providerId?: string,
|
|
1257
|
+
options?: OAuthSelectorOptions,
|
|
1258
|
+
): Promise<void> {
|
|
1236
1259
|
if (providerId) {
|
|
1237
1260
|
const oauthProvider = getOAuthProviders().find(provider => provider.id === providerId);
|
|
1238
1261
|
if (!oauthProvider && !this.ctx.session.modelRegistry.getModelProfiles().has(providerId)) {
|
|
@@ -1259,6 +1282,45 @@ export class SelectorController {
|
|
|
1259
1282
|
}
|
|
1260
1283
|
}
|
|
1261
1284
|
|
|
1285
|
+
let externalCredentialCandidates: ReturnType<typeof filterAutoImportOAuthCredentials> = [];
|
|
1286
|
+
if (
|
|
1287
|
+
mode === "login" &&
|
|
1288
|
+
providerId === undefined &&
|
|
1289
|
+
options?.allowExternalCredentialDiscovery === true &&
|
|
1290
|
+
options.trigger === "bare-login"
|
|
1291
|
+
) {
|
|
1292
|
+
const preview = await runExternalCredentialAutoImport({
|
|
1293
|
+
authStorage: {
|
|
1294
|
+
importCredentialIfAbsent: async () => ({
|
|
1295
|
+
inserted: false,
|
|
1296
|
+
reason: "skipped-existing",
|
|
1297
|
+
provider: "",
|
|
1298
|
+
entries: [],
|
|
1299
|
+
}),
|
|
1300
|
+
},
|
|
1301
|
+
trigger: "bare-login",
|
|
1302
|
+
discover: options.externalCredentialDiscover,
|
|
1303
|
+
});
|
|
1304
|
+
const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
1305
|
+
const candidates = filterAutoImportOAuthCredentials(result.importable);
|
|
1306
|
+
if (candidates.length > 0) {
|
|
1307
|
+
const confirmed = await this.ctx.showHookConfirm(
|
|
1308
|
+
`Import ${candidates.length} external credential(s)?`,
|
|
1309
|
+
`${formatDiscoverySummary({ ...result, importable: candidates }).join("\n")}\n\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`,
|
|
1310
|
+
);
|
|
1311
|
+
if (confirmed) {
|
|
1312
|
+
const summary = await runExternalCredentialAutoImport({
|
|
1313
|
+
authStorage: this.ctx.session.modelRegistry.authStorage,
|
|
1314
|
+
trigger: "bare-login",
|
|
1315
|
+
discover: options.externalCredentialDiscover,
|
|
1316
|
+
});
|
|
1317
|
+
externalCredentialCandidates = summary.imported;
|
|
1318
|
+
if (externalCredentialCandidates.length > 0) {
|
|
1319
|
+
await this.ctx.session.modelRegistry.refresh("offline");
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1262
1324
|
this.showSelector(done => {
|
|
1263
1325
|
let selector: OAuthSelectorComponent;
|
|
1264
1326
|
selector = new OAuthSelectorComponent(
|
|
@@ -1289,6 +1351,7 @@ export class SelectorController {
|
|
|
1289
1351
|
requestRender: () => {
|
|
1290
1352
|
this.ctx.ui.requestRender();
|
|
1291
1353
|
},
|
|
1354
|
+
externalCredentialCandidates,
|
|
1292
1355
|
},
|
|
1293
1356
|
);
|
|
1294
1357
|
return { component: selector, focus: selector };
|
|
@@ -2502,8 +2502,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2502
2502
|
return this.#selectorController.handleSessionDeleteCommand();
|
|
2503
2503
|
}
|
|
2504
2504
|
|
|
2505
|
-
showOAuthSelector(
|
|
2506
|
-
|
|
2505
|
+
showOAuthSelector(
|
|
2506
|
+
mode: "login" | "logout",
|
|
2507
|
+
providerId?: string,
|
|
2508
|
+
options?: import("./types").OAuthSelectorOptions,
|
|
2509
|
+
): Promise<void> {
|
|
2510
|
+
return this.#selectorController.showOAuthSelector(mode, providerId, options);
|
|
2507
2511
|
}
|
|
2508
2512
|
|
|
2509
2513
|
showHookConfirm(title: string, message: string): Promise<boolean> {
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
* - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import * as path from "node:path";
|
|
15
14
|
import { $pickenv, logger, readLines, Snowflake } from "@gajae-code/utils";
|
|
16
15
|
import type {
|
|
17
16
|
ExtensionUIContext,
|
|
18
17
|
ExtensionUIDialogOptions,
|
|
19
18
|
ExtensionWidgetOptions,
|
|
20
19
|
} from "../../extensibility/extensions";
|
|
20
|
+
import { workflowGatePath } from "../../gjc-runtime/session-layout";
|
|
21
21
|
import { type Theme, theme } from "../../modes/theme/theme";
|
|
22
22
|
import type { AgentSession } from "../../session/agent-session";
|
|
23
23
|
import { initializeExtensions } from "../runtime-init";
|
|
@@ -336,7 +336,7 @@ export async function runRpcMode(
|
|
|
336
336
|
// Unattended control plane (#318/#319/#323/G011): routes negotiate_unattended +
|
|
337
337
|
// workflow_gate_response and lets skill runtimes emit gates over RPC.
|
|
338
338
|
const gateStore = new FileGateStore(
|
|
339
|
-
|
|
339
|
+
workflowGatePath(session.sessionManager.getCwd(), session.sessionId, session.sessionId),
|
|
340
340
|
);
|
|
341
341
|
const unattendedControlPlane = new UnattendedSessionControlPlane({
|
|
342
342
|
runId: session.sessionId,
|
|
@@ -78,6 +78,7 @@ export async function initializeExtensions(session: AgentSession, options: Initi
|
|
|
78
78
|
shutdown,
|
|
79
79
|
getContextUsage: () => session.getContextUsage(),
|
|
80
80
|
getSystemPrompt: () => session.systemPrompt,
|
|
81
|
+
getWorkflowGate: () => session.getWorkflowGateEmitter(),
|
|
81
82
|
compact: instructionsOrOptions => runExtensionCompact(session, instructionsOrOptions),
|
|
82
83
|
},
|
|
83
84
|
// ExtensionCommandContextActions — commands invokable via prompt("/command")
|
|
@@ -50,6 +50,7 @@ export function agentSessionEventType(event: AgentSessionEvent): AgentWireEventT
|
|
|
50
50
|
case "todo_reminder":
|
|
51
51
|
case "todo_auto_clear":
|
|
52
52
|
case "irc_message":
|
|
53
|
+
case "subagent_steer_message":
|
|
53
54
|
case "notice":
|
|
54
55
|
case "thinking_level_changed":
|
|
55
56
|
case "goal_updated":
|