@gajae-code/coding-agent 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/commands/contribution-prep.d.ts +18 -0
- package/dist/types/commands/deep-interview.d.ts +41 -0
- package/dist/types/commands/session.d.ts +24 -0
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/config/model-registry.d.ts +2 -2
- package/dist/types/config/models-config-schema.d.ts +17 -9
- package/dist/types/config/settings-schema.d.ts +37 -24
- package/dist/types/discovery/helpers.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +33 -0
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -11
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +25 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +13 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +37 -5
- package/dist/types/gjc-runtime/tmux-common.d.ts +41 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +17 -0
- package/dist/types/goals/runtime.d.ts +3 -9
- package/dist/types/goals/state.d.ts +3 -6
- package/dist/types/goals/tools/goal-tool.d.ts +1 -69
- package/dist/types/hooks/skill-state.d.ts +5 -0
- package/dist/types/memories/index.d.ts +1 -1
- package/dist/types/memory-backend/local-backend.d.ts +3 -3
- package/dist/types/modes/components/hook-selector.d.ts +7 -0
- package/dist/types/modes/components/settings-selector.d.ts +0 -2
- package/dist/types/modes/components/status-line/types.d.ts +0 -3
- package/dist/types/modes/components/status-line.d.ts +0 -3
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -12
- package/dist/types/modes/theme/defaults/index.d.ts +0 -2
- package/dist/types/modes/theme/theme.d.ts +1 -2
- package/dist/types/modes/types.d.ts +1 -7
- package/dist/types/modes/utils/context-usage.d.ts +6 -2
- package/dist/types/sdk.d.ts +6 -2
- package/dist/types/session/agent-session.d.ts +47 -1
- package/dist/types/session/contribution-prep.d.ts +47 -0
- package/dist/types/session/session-manager.d.ts +3 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
- package/dist/types/setup/provider-onboarding.d.ts +29 -5
- package/dist/types/skill-state/active-state.d.ts +30 -1
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +6 -1
- package/dist/types/skill-state/initial-phase.d.ts +12 -0
- package/dist/types/skill-state/workflow-hud.d.ts +9 -4
- package/dist/types/skill-state/workflow-state-contract.d.ts +34 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/types.d.ts +11 -0
- package/dist/types/tools/index.d.ts +20 -1
- package/dist/types/tools/skill.d.ts +47 -0
- package/dist/types/utils/changelog.d.ts +18 -2
- package/package.json +7 -7
- package/src/cli/args.ts +3 -2
- package/src/cli/setup-cli.ts +26 -12
- package/src/cli.ts +7 -1
- package/src/commands/contribution-prep.ts +41 -0
- package/src/commands/deep-interview.ts +30 -23
- package/src/commands/launch.ts +10 -1
- package/src/commands/ralplan.ts +10 -22
- package/src/commands/session.ts +150 -0
- package/src/commands/setup.ts +2 -0
- package/src/commands/state.ts +15 -4
- package/src/commands/team.ts +23 -3
- package/src/config/model-registry.ts +10 -2
- package/src/config/models-config-schema.ts +120 -102
- package/src/config/settings-schema.ts +42 -25
- package/src/config.ts +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +32 -13
- package/src/defaults/gjc/skills/ralplan/SKILL.md +22 -2
- package/src/defaults/gjc/skills/team/SKILL.md +39 -7
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +33 -25
- package/src/discovery/helpers.ts +24 -1
- package/src/eval/py/prelude.py +1 -1
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +546 -0
- package/src/gjc-runtime/goal-mode-request.ts +2 -19
- package/src/gjc-runtime/launch-tmux.ts +83 -43
- package/src/gjc-runtime/ralplan-runtime.ts +460 -0
- package/src/gjc-runtime/state-runtime.ts +731 -0
- package/src/gjc-runtime/team-runtime.ts +708 -52
- package/src/gjc-runtime/tmux-common.ts +119 -0
- package/src/gjc-runtime/tmux-sessions.ts +165 -0
- package/src/gjc-runtime/ultragoal-guard.ts +6 -3
- package/src/gjc-runtime/ultragoal-runtime.ts +5 -4
- package/src/goals/runtime.ts +38 -144
- package/src/goals/state.ts +36 -7
- package/src/goals/tools/goal-tool.ts +15 -172
- package/src/hooks/skill-state.ts +39 -18
- package/src/internal-urls/docs-index.generated.ts +5 -4
- package/src/internal-urls/memory-protocol.ts +3 -2
- package/src/main.ts +2 -3
- package/src/memories/index.ts +2 -1
- package/src/memory-backend/local-backend.ts +14 -6
- package/src/modes/components/hook-selector.ts +156 -1
- package/src/modes/components/settings-selector.ts +5 -12
- package/src/modes/components/skill-hud/render.ts +4 -0
- package/src/modes/components/status-line/segments.ts +5 -16
- package/src/modes/components/status-line/types.ts +0 -3
- package/src/modes/components/status-line.ts +0 -6
- package/src/modes/controllers/command-controller.ts +27 -4
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +0 -15
- package/src/modes/controllers/selector-controller.ts +4 -11
- package/src/modes/interactive-mode.ts +18 -219
- package/src/modes/theme/defaults/dark-poimandres.json +0 -1
- package/src/modes/theme/defaults/light-poimandres.json +0 -1
- package/src/modes/theme/theme.ts +0 -6
- package/src/modes/types.ts +1 -7
- package/src/modes/utils/context-usage.ts +66 -17
- package/src/prompts/agents/architect.md +3 -0
- package/src/prompts/agents/executor.md +2 -0
- package/src/prompts/agents/frontmatter.md +1 -0
- package/src/prompts/goals/goal-continuation.md +1 -4
- package/src/prompts/goals/goal-mode-active.md +3 -5
- package/src/prompts/system/subagent-system-prompt.md +6 -0
- package/src/prompts/system/system-prompt.md +5 -7
- package/src/prompts/tools/goal.md +4 -4
- package/src/prompts/tools/skill.md +28 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/sdk.ts +51 -11
- package/src/session/agent-session.ts +222 -21
- package/src/session/contribution-prep.ts +320 -0
- package/src/session/session-manager.ts +9 -1
- package/src/setup/model-onboarding-guidance.ts +6 -3
- package/src/setup/provider-onboarding.ts +177 -16
- package/src/skill-state/active-state.ts +188 -25
- package/src/skill-state/deep-interview-mutation-guard.ts +72 -21
- package/src/skill-state/initial-phase.ts +17 -0
- package/src/skill-state/workflow-hud.ts +23 -5
- package/src/skill-state/workflow-state-contract.ts +121 -0
- package/src/slash-commands/builtin-registry.ts +75 -25
- package/src/slash-commands/helpers/context-report.ts +123 -13
- package/src/task/agents.ts +1 -0
- package/src/task/commands.ts +1 -5
- package/src/task/executor.ts +9 -1
- package/src/task/index.ts +91 -4
- package/src/task/types.ts +6 -0
- package/src/tools/ask.ts +2 -0
- package/src/tools/gh.ts +212 -2
- package/src/tools/index.ts +25 -6
- package/src/tools/skill.ts +153 -0
- package/src/utils/changelog.ts +67 -44
- package/dist/types/commands/gjc-runtime-bridge.d.ts +0 -30
- package/dist/types/commands/question.d.ts +0 -7
- package/dist/types/modes/loop-limit.d.ts +0 -22
- package/src/commands/gjc-runtime-bridge.ts +0 -227
- package/src/commands/question.ts +0 -12
- package/src/modes/loop-limit.ts +0 -140
- package/src/prompts/commands/orchestrate.md +0 -49
- package/src/prompts/goals/goal-budget-limit.md +0 -16
- package/src/prompts/tools/create-goal.md +0 -3
- package/src/prompts/tools/get-goal.md +0 -3
- package/src/prompts/tools/update-goal.md +0 -3
package/src/cli/setup-cli.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { theme } from "../modes/theme/theme";
|
|
17
17
|
import {
|
|
18
18
|
addApiCompatibleProvider,
|
|
19
|
+
formatProviderPresetList,
|
|
19
20
|
formatProviderSetupResult,
|
|
20
21
|
parseProviderCompatibility,
|
|
21
22
|
} from "../setup/provider-onboarding";
|
|
@@ -28,6 +29,7 @@ export interface SetupCommandArgs {
|
|
|
28
29
|
json?: boolean;
|
|
29
30
|
check?: boolean;
|
|
30
31
|
force?: boolean;
|
|
32
|
+
preset?: string;
|
|
31
33
|
compat?: string;
|
|
32
34
|
provider?: string;
|
|
33
35
|
baseUrl?: string;
|
|
@@ -42,6 +44,7 @@ const VALID_COMPONENTS: SetupComponent[] = ["defaults", "hooks", "provider", "py
|
|
|
42
44
|
function hasProviderSetupFlags(flags: SetupCommandArgs["flags"]): boolean {
|
|
43
45
|
return (
|
|
44
46
|
flags.compat !== undefined ||
|
|
47
|
+
flags.preset !== undefined ||
|
|
45
48
|
flags.provider !== undefined ||
|
|
46
49
|
flags.baseUrl !== undefined ||
|
|
47
50
|
flags.apiKeyEnv !== undefined ||
|
|
@@ -57,7 +60,7 @@ function rejectProviderFlagsOutsideProvider(component: SetupComponent, flags: Se
|
|
|
57
60
|
console.error(chalk.red("Provider setup flags require the explicit `provider` component."));
|
|
58
61
|
console.error(
|
|
59
62
|
chalk.dim(
|
|
60
|
-
`Run: ${APP_NAME} setup provider --compat <openai|anthropic> --provider <id> --base-url <url> --api-key-env <ENV> --model <id>`,
|
|
63
|
+
`Run: ${APP_NAME} setup provider --preset <minimax|glm> or ${APP_NAME} setup provider --compat <openai|anthropic> --provider <id> --base-url <url> --api-key-env <ENV> --model <id>`,
|
|
61
64
|
),
|
|
62
65
|
);
|
|
63
66
|
process.exit(1);
|
|
@@ -87,6 +90,8 @@ export function parseSetupArgs(args: string[]): SetupCommandArgs | undefined {
|
|
|
87
90
|
flags.force = true;
|
|
88
91
|
} else if (arg === "--compat") {
|
|
89
92
|
flags.compat = args[++i];
|
|
93
|
+
} else if (arg === "--preset") {
|
|
94
|
+
flags.preset = args[++i];
|
|
90
95
|
} else if (arg === "--provider") {
|
|
91
96
|
flags.provider = args[++i];
|
|
92
97
|
} else if (arg === "--base-url") {
|
|
@@ -190,6 +195,7 @@ export async function runSetupCommand(cmd: SetupCommandArgs): Promise<void> {
|
|
|
190
195
|
async function handleProviderSetup(flags: {
|
|
191
196
|
json?: boolean;
|
|
192
197
|
force?: boolean;
|
|
198
|
+
preset?: string;
|
|
193
199
|
compat?: string;
|
|
194
200
|
provider?: string;
|
|
195
201
|
baseUrl?: string;
|
|
@@ -199,20 +205,25 @@ async function handleProviderSetup(flags: {
|
|
|
199
205
|
}): Promise<void> {
|
|
200
206
|
try {
|
|
201
207
|
const missing: string[] = [];
|
|
202
|
-
if (!flags.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
if (!flags.preset) {
|
|
209
|
+
if (!flags.compat) missing.push("--compat");
|
|
210
|
+
if (!flags.provider) missing.push("--provider");
|
|
211
|
+
if (!flags.baseUrl) missing.push("--base-url");
|
|
212
|
+
if (!flags.apiKeyEnv) missing.push("--api-key-env");
|
|
213
|
+
if (!flags.model || flags.model.length === 0) missing.push("--model");
|
|
214
|
+
}
|
|
207
215
|
if (missing.length > 0) {
|
|
208
|
-
throw new Error(
|
|
216
|
+
throw new Error(
|
|
217
|
+
`Missing required provider setup option(s): ${missing.join(", ")}. Or use --preset <preset>.\nAvailable presets:\n${formatProviderPresetList()}`,
|
|
218
|
+
);
|
|
209
219
|
}
|
|
210
220
|
const result = await addApiCompatibleProvider({
|
|
211
|
-
compatibility: parseProviderCompatibility(flags.compat
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
compatibility: flags.compat ? parseProviderCompatibility(flags.compat) : undefined,
|
|
222
|
+
preset: flags.preset,
|
|
223
|
+
providerId: flags.provider,
|
|
224
|
+
baseUrl: flags.baseUrl,
|
|
214
225
|
apiKeyEnv: flags.apiKeyEnv,
|
|
215
|
-
models: flags.model
|
|
226
|
+
models: flags.model,
|
|
216
227
|
modelsPath: flags.modelsPath,
|
|
217
228
|
force: flags.force,
|
|
218
229
|
});
|
|
@@ -400,18 +411,21 @@ ${chalk.bold("Usage:")}
|
|
|
400
411
|
${chalk.bold("Components:")}
|
|
401
412
|
defaults Install bundled GJC default workflow skills (default)
|
|
402
413
|
hooks Optional: install GJC native Codex UserPromptSubmit/Stop skill-state hooks
|
|
403
|
-
provider Optional: add
|
|
414
|
+
provider Optional: add a preset, OpenAI-compatible, or Anthropic-compatible API provider
|
|
404
415
|
python Optional: verify a Python 3 interpreter is reachable for code execution
|
|
405
416
|
stt Optional: install speech-to-text dependencies (openai-whisper, recording tools)
|
|
406
417
|
|
|
407
418
|
|
|
408
419
|
${chalk.bold("Provider example:")}
|
|
420
|
+
${APP_NAME} setup provider --preset minimax
|
|
421
|
+
${APP_NAME} setup provider --preset glm
|
|
409
422
|
MY_PROVIDER_KEY=sk-... ${APP_NAME} setup provider --compat openai --provider my-oai --base-url https://api.example.com/v1 --api-key-env MY_PROVIDER_KEY --model gpt-example
|
|
410
423
|
|
|
411
424
|
${chalk.bold("Options:")}
|
|
412
425
|
-c, --check Check if dependencies are installed without installing
|
|
413
426
|
-f, --force Overwrite existing default workflow skill files
|
|
414
427
|
--json Output status as JSON
|
|
428
|
+
--preset Provider preset: minimax, minimax-cn, or glm (aliases include minimax-code and zai)
|
|
415
429
|
--compat Provider compatibility: openai or anthropic
|
|
416
430
|
--provider Provider id to add to models.yml
|
|
417
431
|
--base-url Provider API base URL
|
package/src/cli.ts
CHANGED
|
@@ -31,14 +31,20 @@ process.title = APP_NAME;
|
|
|
31
31
|
|
|
32
32
|
const commands: CommandEntry[] = [
|
|
33
33
|
{ name: "codex-native-hook", load: () => import("./commands/codex-native-hook").then(m => m.default) },
|
|
34
|
-
{ name: "question", load: () => import("./commands/question").then(m => m.default) },
|
|
35
34
|
{ name: "state", load: () => import("./commands/state").then(m => m.default) },
|
|
36
35
|
{ name: "setup", load: () => import("./commands/setup").then(m => m.default) },
|
|
37
36
|
{ name: "skills", load: () => import("./commands/skills").then(m => m.default) },
|
|
37
|
+
{ name: "session", load: () => import("./commands/session").then(m => m.default) },
|
|
38
38
|
{ name: "team", load: () => import("./commands/team").then(m => m.default) },
|
|
39
39
|
{ name: "ultragoal", load: () => import("./commands/ultragoal").then(m => m.default) },
|
|
40
40
|
{ name: "ralplan", load: () => import("./commands/ralplan").then(m => m.default) },
|
|
41
|
+
{
|
|
42
|
+
name: "contribute-pr",
|
|
43
|
+
aliases: ["contribution-prep"],
|
|
44
|
+
load: () => import("./commands/contribution-prep").then(m => m.default),
|
|
45
|
+
},
|
|
41
46
|
{ name: "deep-interview", load: () => import("./commands/deep-interview").then(m => m.default) },
|
|
47
|
+
{ name: "update", load: () => import("./commands/update").then(m => m.default) },
|
|
42
48
|
{ name: "launch", load: () => import("./commands/launch").then(m => m.default) },
|
|
43
49
|
];
|
|
44
50
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Command, Flags } from "@gajae-code/utils/cli";
|
|
2
|
+
import { prepareContributionPrep } from "../session/contribution-prep";
|
|
3
|
+
|
|
4
|
+
function writeText(lines: string[]): void {
|
|
5
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default class ContributionPrep extends Command {
|
|
9
|
+
static description = "Dump redacted context and prepare a fresh contribute-pr worker prompt";
|
|
10
|
+
static strict = false;
|
|
11
|
+
|
|
12
|
+
static flags = {
|
|
13
|
+
"no-spawn": Flags.boolean({ description: "Only write artifacts; do not spawn a fresh GJC worker" }),
|
|
14
|
+
"source-session-id": Flags.string({ description: "Source session id to record in the manifest" }),
|
|
15
|
+
"artifact-root": Flags.string({ description: "Directory where contribute-pr artifacts are written" }),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
static examples = ["gjc contribute-pr", "gjc contribute-pr --no-spawn"];
|
|
19
|
+
|
|
20
|
+
async run(): Promise<void> {
|
|
21
|
+
const { flags } = await this.parse(ContributionPrep);
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
const result = await prepareContributionPrep(
|
|
24
|
+
{
|
|
25
|
+
sessionId: flags["source-session-id"] ?? "cli",
|
|
26
|
+
cwd,
|
|
27
|
+
messages: [],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
spawnWorker: !flags["no-spawn"],
|
|
31
|
+
artifactRoot: flags["artifact-root"],
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
writeText([
|
|
35
|
+
"Contribution prep artifacts written.",
|
|
36
|
+
`Manifest: ${result.manifestPath}`,
|
|
37
|
+
`Worker prompt: ${result.workerPromptPath}`,
|
|
38
|
+
`Spawned worker: ${result.spawned ? "yes" : "no"}`,
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,31 +1,38 @@
|
|
|
1
|
-
import { Command } from "@gajae-code/utils/cli";
|
|
2
|
-
import {
|
|
3
|
-
import { runGjcRuntimeBridgeWithHudSidecar } from "./gjc-runtime-bridge";
|
|
1
|
+
import { Command, Flags } from "@gajae-code/utils/cli";
|
|
2
|
+
import { runNativeDeepInterviewCommand } from "../gjc-runtime/deep-interview-runtime";
|
|
4
3
|
|
|
5
4
|
export default class DeepInterview extends Command {
|
|
6
|
-
static description = "Run
|
|
5
|
+
static description = "Run native GJC deep-interview workflow";
|
|
7
6
|
static strict = false;
|
|
8
|
-
static
|
|
7
|
+
static flags = {
|
|
8
|
+
quick: Flags.boolean({ description: "Seed a quick deep-interview run" }),
|
|
9
|
+
standard: Flags.boolean({ description: "Seed a standard deep-interview run" }),
|
|
10
|
+
deep: Flags.boolean({ description: "Seed a deep deep-interview run" }),
|
|
11
|
+
threshold: Flags.string({ description: "Override ambiguity threshold for kickoff" }),
|
|
12
|
+
"threshold-source": Flags.string({ description: "Describe the threshold override source" }),
|
|
13
|
+
"session-id": Flags.string({
|
|
14
|
+
description: "Route state/spec handoff through a session-scoped .gjc state directory",
|
|
15
|
+
}),
|
|
16
|
+
write: Flags.boolean({ description: "Persist a final deep-interview spec through the sanctioned GJC CLI/API" }),
|
|
17
|
+
stage: Flags.string({ description: 'Spec stage for --write (currently "final")' }),
|
|
18
|
+
slug: Flags.string({ description: "Safe slug for .gjc/specs/deep-interview-<slug>.md" }),
|
|
19
|
+
spec: Flags.string({ description: "Final spec markdown or a path to the final spec markdown" }),
|
|
20
|
+
handoff: Flags.string({ description: 'After --write, hand off to a workflow target (currently "ralplan")' }),
|
|
21
|
+
deliberate: Flags.boolean({
|
|
22
|
+
description: "Shortcut for --write handoff to ralplan in deliberate consensus mode",
|
|
23
|
+
}),
|
|
24
|
+
json: Flags.boolean({ description: "Output JSON" }),
|
|
25
|
+
};
|
|
26
|
+
static examples = [
|
|
27
|
+
'$ gjc deep-interview --standard "<idea>"',
|
|
28
|
+
"$ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md",
|
|
29
|
+
"$ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md --deliberate",
|
|
30
|
+
];
|
|
9
31
|
|
|
10
32
|
async run(): Promise<void> {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
sidecarSkill: "deep-interview",
|
|
15
|
-
onHudPayload: payload =>
|
|
16
|
-
syncSkillActiveState({
|
|
17
|
-
cwd,
|
|
18
|
-
skill: "deep-interview",
|
|
19
|
-
active: payload.active ?? true,
|
|
20
|
-
phase: payload.phase,
|
|
21
|
-
sessionId: payload.session_id,
|
|
22
|
-
threadId: payload.thread_id,
|
|
23
|
-
turnId: payload.turn_id,
|
|
24
|
-
hud: payload.hud,
|
|
25
|
-
source: "gjc-runtime-bridge",
|
|
26
|
-
}),
|
|
27
|
-
});
|
|
28
|
-
if (result.error) process.stderr.write(`${result.error}\n`);
|
|
33
|
+
const result = await runNativeDeepInterviewCommand(this.argv, process.cwd());
|
|
34
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
35
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
29
36
|
process.exitCode = result.status;
|
|
30
37
|
}
|
|
31
38
|
}
|
package/src/commands/launch.ts
CHANGED
|
@@ -155,7 +155,16 @@ export default class Index extends Command {
|
|
|
155
155
|
setProjectDir(launch.cwd);
|
|
156
156
|
}
|
|
157
157
|
const launchParsed = parseArgs(launch.args);
|
|
158
|
-
if (
|
|
158
|
+
if (
|
|
159
|
+
launchDefaultTmuxIfNeeded({
|
|
160
|
+
parsed: launchParsed,
|
|
161
|
+
rawArgs: launch.args,
|
|
162
|
+
cwd: launch.cwd,
|
|
163
|
+
worktreeBranch: launch.worktree.enabled && !launch.worktree.detached ? launch.worktree.branchName : null,
|
|
164
|
+
project: launch.worktree.enabled ? launch.worktree.repoRoot : launch.cwd,
|
|
165
|
+
})
|
|
166
|
+
)
|
|
167
|
+
return;
|
|
159
168
|
await runRootCommand(launchParsed, launch.args);
|
|
160
169
|
}
|
|
161
170
|
}
|
package/src/commands/ralplan.ts
CHANGED
|
@@ -1,31 +1,19 @@
|
|
|
1
1
|
import { Command } from "@gajae-code/utils/cli";
|
|
2
|
-
import {
|
|
3
|
-
import { runGjcRuntimeBridgeWithHudSidecar } from "./gjc-runtime-bridge";
|
|
2
|
+
import { runNativeRalplanCommand } from "../gjc-runtime/ralplan-runtime";
|
|
4
3
|
|
|
5
4
|
export default class Ralplan extends Command {
|
|
6
|
-
static description = "Run
|
|
5
|
+
static description = "Run native GJC RALPLAN consensus planning workflow";
|
|
7
6
|
static strict = false;
|
|
8
|
-
static examples = [
|
|
7
|
+
static examples = [
|
|
8
|
+
'$ gjc ralplan "<task description>"',
|
|
9
|
+
'$ gjc ralplan --interactive --deliberate "<task description>"',
|
|
10
|
+
'$ gjc ralplan --write --stage planner --stage_n 1 --artifact "<markdown or path>"',
|
|
11
|
+
];
|
|
9
12
|
|
|
10
13
|
async run(): Promise<void> {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
sidecarSkill: "ralplan",
|
|
15
|
-
onHudPayload: payload =>
|
|
16
|
-
syncSkillActiveState({
|
|
17
|
-
cwd,
|
|
18
|
-
skill: "ralplan",
|
|
19
|
-
active: payload.active ?? true,
|
|
20
|
-
phase: payload.phase,
|
|
21
|
-
sessionId: payload.session_id,
|
|
22
|
-
threadId: payload.thread_id,
|
|
23
|
-
turnId: payload.turn_id,
|
|
24
|
-
hud: payload.hud,
|
|
25
|
-
source: "gjc-runtime-bridge",
|
|
26
|
-
}),
|
|
27
|
-
});
|
|
28
|
-
if (result.error) process.stderr.write(`${result.error}\n`);
|
|
14
|
+
const result = await runNativeRalplanCommand(this.argv, process.cwd());
|
|
15
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
16
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
29
17
|
process.exitCode = result.status;
|
|
30
18
|
}
|
|
31
19
|
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
2
|
+
import {
|
|
3
|
+
attachGjcTmuxSession,
|
|
4
|
+
createGjcTmuxSession,
|
|
5
|
+
listGjcTmuxSessions,
|
|
6
|
+
removeGjcTmuxSession,
|
|
7
|
+
statusGjcTmuxSession,
|
|
8
|
+
} from "../gjc-runtime/tmux-sessions";
|
|
9
|
+
|
|
10
|
+
function writeJson(value: unknown): void {
|
|
11
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function writeText(lines: string[]): void {
|
|
15
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function writeJsonFailure(error: unknown): void {
|
|
19
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20
|
+
const [reason = "session_error"] = message.split(":");
|
|
21
|
+
writeJson({ ok: false, reason });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface SessionJsonDto {
|
|
25
|
+
name: string;
|
|
26
|
+
attached: boolean;
|
|
27
|
+
windows: number;
|
|
28
|
+
panes: number;
|
|
29
|
+
bindings: string;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sessionJson(session: SessionJsonDto): SessionJsonDto {
|
|
34
|
+
return {
|
|
35
|
+
name: session.name,
|
|
36
|
+
attached: session.attached,
|
|
37
|
+
windows: session.windows,
|
|
38
|
+
panes: session.panes,
|
|
39
|
+
bindings: session.bindings,
|
|
40
|
+
createdAt: session.createdAt,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default class Session extends Command {
|
|
45
|
+
static description = "List, inspect, attach, and remove tagged GJC-managed tmux sessions";
|
|
46
|
+
static strict = false;
|
|
47
|
+
|
|
48
|
+
static args = {
|
|
49
|
+
action: Args.string({
|
|
50
|
+
description: "list (default), status, create, attach, or remove",
|
|
51
|
+
required: false,
|
|
52
|
+
}),
|
|
53
|
+
session: Args.string({
|
|
54
|
+
description: "Session name for status, attach, or remove",
|
|
55
|
+
required: false,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
static flags = {
|
|
60
|
+
json: Flags.boolean({ char: "j", description: "Emit machine-readable JSON", default: false }),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
static examples = [
|
|
64
|
+
"gjc session list",
|
|
65
|
+
"gjc session create",
|
|
66
|
+
"gjc session status <session>",
|
|
67
|
+
"gjc session attach <session>",
|
|
68
|
+
"gjc session remove <session>",
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
async run(): Promise<void> {
|
|
72
|
+
const { args, flags } = await this.parse(Session);
|
|
73
|
+
const action = args.action ?? "list";
|
|
74
|
+
const sessionName = args.session;
|
|
75
|
+
const json = flags.json ?? false;
|
|
76
|
+
try {
|
|
77
|
+
if (action === "list") {
|
|
78
|
+
const sessions = listGjcTmuxSessions();
|
|
79
|
+
if (json) {
|
|
80
|
+
writeJson({ ok: true, sessions: sessions.map(sessionJson) });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
writeText(
|
|
84
|
+
sessions.map(session =>
|
|
85
|
+
[
|
|
86
|
+
session.name,
|
|
87
|
+
`windows=${session.windows}`,
|
|
88
|
+
`attached=${session.attached}`,
|
|
89
|
+
`createdAt=${session.createdAt}`,
|
|
90
|
+
`panes=${session.panes}`,
|
|
91
|
+
`bindings=${session.bindings || "none"}`,
|
|
92
|
+
].join("\t"),
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (action === "create") {
|
|
99
|
+
const session = createGjcTmuxSession();
|
|
100
|
+
if (json) {
|
|
101
|
+
writeJson({ ok: true, session: sessionJson(session) });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
writeText([`created: ${session.name}`]);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!sessionName) throw new Error("missing_session_name");
|
|
109
|
+
|
|
110
|
+
if (action === "status") {
|
|
111
|
+
const session = statusGjcTmuxSession(sessionName);
|
|
112
|
+
if (json) {
|
|
113
|
+
writeJson({ ok: true, session: sessionJson(session) });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
writeText([
|
|
117
|
+
`session: ${session.name}`,
|
|
118
|
+
`windows: ${session.windows}`,
|
|
119
|
+
`attached: ${session.attached}`,
|
|
120
|
+
`createdAt: ${session.createdAt}`,
|
|
121
|
+
`panes: ${session.panes}`,
|
|
122
|
+
`bindings: ${session.bindings || "none"}`,
|
|
123
|
+
]);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (action === "remove" || action === "rm" || action === "delete") {
|
|
128
|
+
const removed = removeGjcTmuxSession(sessionName);
|
|
129
|
+
if (json) {
|
|
130
|
+
writeJson({ ok: true, session: sessionJson(removed) });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
writeText([`removed: ${removed.name}`]);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (action === "attach") {
|
|
138
|
+
attachGjcTmuxSession(sessionName);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
throw new Error(`unknown_session_action:${action}`);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (json) {
|
|
144
|
+
writeJsonFailure(error);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -22,6 +22,7 @@ export default class Setup extends Command {
|
|
|
22
22
|
check: Flags.boolean({ char: "c", description: "Check if dependencies are installed" }),
|
|
23
23
|
force: Flags.boolean({ char: "f", description: "Overwrite existing default workflow skill files" }),
|
|
24
24
|
json: Flags.boolean({ description: "Output status as JSON" }),
|
|
25
|
+
preset: Flags.string({ description: "Provider preset: minimax, minimax-cn, or glm" }),
|
|
25
26
|
compat: Flags.string({ description: "Provider compatibility: openai or anthropic" }),
|
|
26
27
|
provider: Flags.string({ description: "Provider id to add to models.yml" }),
|
|
27
28
|
"base-url": Flags.string({ description: "Provider API base URL" }),
|
|
@@ -38,6 +39,7 @@ export default class Setup extends Command {
|
|
|
38
39
|
json: flags.json,
|
|
39
40
|
check: flags.check,
|
|
40
41
|
force: flags.force,
|
|
42
|
+
preset: flags.preset,
|
|
41
43
|
compat: flags.compat,
|
|
42
44
|
provider: flags.provider,
|
|
43
45
|
baseUrl: flags["base-url"],
|
package/src/commands/state.ts
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { Command } from "@gajae-code/utils/cli";
|
|
2
|
-
import {
|
|
2
|
+
import { runNativeStateCommand } from "../gjc-runtime/state-runtime";
|
|
3
3
|
|
|
4
4
|
export default class State extends Command {
|
|
5
|
-
static description = "Read or update
|
|
5
|
+
static description = "Read or update GJC workflow state receipts under .gjc/state";
|
|
6
6
|
static strict = false;
|
|
7
|
-
static examples = [
|
|
7
|
+
static examples = [
|
|
8
|
+
'$ gjc state read --input \'{"mode":"deep-interview"}\' --json',
|
|
9
|
+
'$ gjc state write --input \'{"state":{"interview_id":"abc"}}\' --mode deep-interview --json',
|
|
10
|
+
"$ gjc state clear --mode deep-interview",
|
|
11
|
+
"$ gjc state deep-interview read --json",
|
|
12
|
+
'$ gjc state ralplan write --input \'{"phase":"approval","active":true}\' --json',
|
|
13
|
+
"$ gjc state team contract",
|
|
14
|
+
"$ gjc state deep-interview handoff --to ralplan --json",
|
|
15
|
+
];
|
|
8
16
|
|
|
9
17
|
async run(): Promise<void> {
|
|
10
|
-
await
|
|
18
|
+
const result = await runNativeStateCommand(this.argv);
|
|
19
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
20
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
21
|
+
process.exitCode = result.status;
|
|
11
22
|
}
|
|
12
23
|
}
|
package/src/commands/team.ts
CHANGED
|
@@ -42,6 +42,18 @@ function formatTaskCounts(counts: Record<string, number>): string {
|
|
|
42
42
|
.join(" ");
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function formatNotificationSummary(snapshot: GjcTeamSnapshot): string {
|
|
46
|
+
const summary = snapshot.notification_summary;
|
|
47
|
+
return `notifications: total=${summary.total} replay_eligible=${summary.replay_eligible} pending=${summary.by_state.pending} queued=${summary.by_state.queued} deferred=${summary.by_state.deferred} failed=${summary.by_state.failed}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function formatAwaitingIntegrationNextStep(snapshot: GjcTeamSnapshot): string[] {
|
|
51
|
+
if (snapshot.phase !== "awaiting_integration") return [];
|
|
52
|
+
return [
|
|
53
|
+
"next: worker tasks are completed, but integration still needs leader attention before the team is complete",
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
function formatIntegrationSummary(snapshot: {
|
|
46
58
|
integration_by_worker?: Record<string, { status?: string; conflict_files?: string[] }>;
|
|
47
59
|
}): string[] {
|
|
@@ -64,7 +76,7 @@ function parseInputFlag(argv: string[]): Record<string, unknown> {
|
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
export default class Team extends Command {
|
|
67
|
-
static description = "Run native GJC tmux team orchestration
|
|
79
|
+
static description = "Run native GJC tmux team orchestration; --dry-run writes ephemeral .gjc/state/team state only";
|
|
68
80
|
static strict = false;
|
|
69
81
|
|
|
70
82
|
static args = {
|
|
@@ -76,13 +88,18 @@ export default class Team extends Command {
|
|
|
76
88
|
|
|
77
89
|
static flags = {
|
|
78
90
|
json: Flags.boolean({ char: "j", description: "Emit machine-readable JSON", default: false }),
|
|
79
|
-
"dry-run": Flags.boolean({
|
|
91
|
+
"dry-run": Flags.boolean({
|
|
92
|
+
description:
|
|
93
|
+
"Create ephemeral .gjc/state/team state without starting tmux panes; do not commit generated state",
|
|
94
|
+
default: false,
|
|
95
|
+
}),
|
|
80
96
|
};
|
|
81
97
|
|
|
82
98
|
static examples = [
|
|
83
99
|
'gjc team 3:executor "Implement the approved plan"',
|
|
84
100
|
"gjc team status <team-name> --json",
|
|
85
101
|
'gjc team api claim-task --input \'{"team_name":"demo","worker_id":"worker-1"}\' --json',
|
|
102
|
+
'gjc team 2:executor --dry-run --json "Preview state only"',
|
|
86
103
|
"gjc team shutdown <team-name>",
|
|
87
104
|
];
|
|
88
105
|
|
|
@@ -118,6 +135,8 @@ export default class Team extends Command {
|
|
|
118
135
|
`state: ${snapshot.state_dir}`,
|
|
119
136
|
`tasks: ${snapshot.task_total} (${formatTaskCounts(snapshot.task_counts)})`,
|
|
120
137
|
`workers: ${snapshot.workers.map(worker => `${worker.id}:${worker.status}`).join(" ")}`,
|
|
138
|
+
formatNotificationSummary(snapshot),
|
|
139
|
+
...formatAwaitingIntegrationNextStep(snapshot),
|
|
121
140
|
...formatIntegrationSummary(snapshot),
|
|
122
141
|
]);
|
|
123
142
|
return;
|
|
@@ -141,7 +160,7 @@ export default class Team extends Command {
|
|
|
141
160
|
if (!operation || operation === "--help" || operation === "help") {
|
|
142
161
|
writeText([
|
|
143
162
|
"Supported operations:",
|
|
144
|
-
"send-message broadcast mailbox-list mailbox-mark-delivered mailbox-mark-notified",
|
|
163
|
+
"send-message broadcast mailbox-list mailbox-mark-delivered mailbox-mark-notified notification-list notification-read notification-replay notification-mark-pane-attempt worker-startup-ack",
|
|
145
164
|
"create-task read-task list-tasks update-task claim-task transition-task-status release-task-claim",
|
|
146
165
|
"read-config read-manifest read-worker-status read-worker-heartbeat update-worker-heartbeat write-worker-inbox write-worker-identity",
|
|
147
166
|
"append-event read-events await-event write-shutdown-request read-shutdown-ack read-monitor-snapshot write-monitor-snapshot read-task-approval write-task-approval",
|
|
@@ -176,6 +195,7 @@ export default class Team extends Command {
|
|
|
176
195
|
`tmux: ${snapshot.tmux_session}`,
|
|
177
196
|
`state: ${snapshot.state_dir}`,
|
|
178
197
|
`workers: ${snapshot.workers.length}`,
|
|
198
|
+
...(dryRun ? ["dry-run: wrote ephemeral .gjc/state/team state only; do not commit generated .gjc state"] : []),
|
|
179
199
|
]);
|
|
180
200
|
}
|
|
181
201
|
}
|
|
@@ -243,6 +243,10 @@ interface ProviderValidationConfig {
|
|
|
243
243
|
models: ProviderValidationModel[];
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
function usesAwsCredentialChain(api: Api | undefined): boolean {
|
|
247
|
+
return api === "bedrock-converse-stream";
|
|
248
|
+
}
|
|
249
|
+
|
|
246
250
|
function validateProviderConfiguration(
|
|
247
251
|
providerName: string,
|
|
248
252
|
config: ProviderValidationConfig,
|
|
@@ -274,10 +278,14 @@ function validateProviderConfiguration(
|
|
|
274
278
|
if (!config.baseUrl) {
|
|
275
279
|
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
|
276
280
|
}
|
|
281
|
+
const usesProviderCredentialChain = usesAwsCredentialChain(config.api);
|
|
277
282
|
const requiresAuth =
|
|
278
283
|
mode === "runtime-register"
|
|
279
|
-
? !config.apiKey && !config.oauthConfigured
|
|
280
|
-
: !
|
|
284
|
+
? !usesProviderCredentialChain && !config.apiKey && !config.oauthConfigured
|
|
285
|
+
: !usesProviderCredentialChain &&
|
|
286
|
+
!config.apiKey &&
|
|
287
|
+
!config.apiKeyEnv &&
|
|
288
|
+
(config.auth ?? "apiKey") !== "none";
|
|
281
289
|
if (requiresAuth) {
|
|
282
290
|
throw new Error(
|
|
283
291
|
mode === "runtime-register"
|