@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.
Files changed (153) hide show
  1. package/CHANGELOG.md +59 -1
  2. package/dist/types/cli/setup-cli.d.ts +1 -0
  3. package/dist/types/commands/contribution-prep.d.ts +18 -0
  4. package/dist/types/commands/deep-interview.d.ts +41 -0
  5. package/dist/types/commands/session.d.ts +24 -0
  6. package/dist/types/commands/setup.d.ts +3 -0
  7. package/dist/types/config/model-registry.d.ts +2 -2
  8. package/dist/types/config/models-config-schema.d.ts +17 -9
  9. package/dist/types/config/settings-schema.d.ts +37 -24
  10. package/dist/types/discovery/helpers.d.ts +2 -0
  11. package/dist/types/extensibility/extensions/types.d.ts +6 -0
  12. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +33 -0
  13. package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
  14. package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -11
  15. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +25 -0
  16. package/dist/types/gjc-runtime/state-runtime.d.ts +13 -0
  17. package/dist/types/gjc-runtime/team-runtime.d.ts +37 -5
  18. package/dist/types/gjc-runtime/tmux-common.d.ts +41 -0
  19. package/dist/types/gjc-runtime/tmux-sessions.d.ts +17 -0
  20. package/dist/types/goals/runtime.d.ts +3 -9
  21. package/dist/types/goals/state.d.ts +3 -6
  22. package/dist/types/goals/tools/goal-tool.d.ts +1 -69
  23. package/dist/types/hooks/skill-state.d.ts +5 -0
  24. package/dist/types/memories/index.d.ts +1 -1
  25. package/dist/types/memory-backend/local-backend.d.ts +3 -3
  26. package/dist/types/modes/components/hook-selector.d.ts +7 -0
  27. package/dist/types/modes/components/settings-selector.d.ts +0 -2
  28. package/dist/types/modes/components/status-line/types.d.ts +0 -3
  29. package/dist/types/modes/components/status-line.d.ts +0 -3
  30. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  31. package/dist/types/modes/interactive-mode.d.ts +1 -12
  32. package/dist/types/modes/theme/defaults/index.d.ts +0 -2
  33. package/dist/types/modes/theme/theme.d.ts +1 -2
  34. package/dist/types/modes/types.d.ts +1 -7
  35. package/dist/types/modes/utils/context-usage.d.ts +6 -2
  36. package/dist/types/sdk.d.ts +6 -2
  37. package/dist/types/session/agent-session.d.ts +47 -1
  38. package/dist/types/session/contribution-prep.d.ts +47 -0
  39. package/dist/types/session/session-manager.d.ts +3 -0
  40. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
  41. package/dist/types/setup/provider-onboarding.d.ts +29 -5
  42. package/dist/types/skill-state/active-state.d.ts +30 -1
  43. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +6 -1
  44. package/dist/types/skill-state/initial-phase.d.ts +12 -0
  45. package/dist/types/skill-state/workflow-hud.d.ts +9 -4
  46. package/dist/types/skill-state/workflow-state-contract.d.ts +34 -0
  47. package/dist/types/task/executor.d.ts +2 -0
  48. package/dist/types/task/types.d.ts +11 -0
  49. package/dist/types/tools/index.d.ts +20 -1
  50. package/dist/types/tools/skill.d.ts +47 -0
  51. package/dist/types/utils/changelog.d.ts +18 -2
  52. package/package.json +7 -7
  53. package/src/cli/args.ts +3 -2
  54. package/src/cli/setup-cli.ts +26 -12
  55. package/src/cli.ts +7 -1
  56. package/src/commands/contribution-prep.ts +41 -0
  57. package/src/commands/deep-interview.ts +30 -23
  58. package/src/commands/launch.ts +10 -1
  59. package/src/commands/ralplan.ts +10 -22
  60. package/src/commands/session.ts +150 -0
  61. package/src/commands/setup.ts +2 -0
  62. package/src/commands/state.ts +15 -4
  63. package/src/commands/team.ts +23 -3
  64. package/src/config/model-registry.ts +10 -2
  65. package/src/config/models-config-schema.ts +120 -102
  66. package/src/config/settings-schema.ts +42 -25
  67. package/src/config.ts +1 -1
  68. package/src/defaults/gjc/skills/deep-interview/SKILL.md +32 -13
  69. package/src/defaults/gjc/skills/ralplan/SKILL.md +22 -2
  70. package/src/defaults/gjc/skills/team/SKILL.md +39 -7
  71. package/src/defaults/gjc/skills/ultragoal/SKILL.md +33 -25
  72. package/src/discovery/helpers.ts +24 -1
  73. package/src/eval/py/prelude.py +1 -1
  74. package/src/extensibility/extensions/types.ts +6 -0
  75. package/src/gjc-runtime/deep-interview-runtime.ts +546 -0
  76. package/src/gjc-runtime/goal-mode-request.ts +2 -19
  77. package/src/gjc-runtime/launch-tmux.ts +83 -43
  78. package/src/gjc-runtime/ralplan-runtime.ts +460 -0
  79. package/src/gjc-runtime/state-runtime.ts +731 -0
  80. package/src/gjc-runtime/team-runtime.ts +708 -52
  81. package/src/gjc-runtime/tmux-common.ts +119 -0
  82. package/src/gjc-runtime/tmux-sessions.ts +165 -0
  83. package/src/gjc-runtime/ultragoal-guard.ts +6 -3
  84. package/src/gjc-runtime/ultragoal-runtime.ts +5 -4
  85. package/src/goals/runtime.ts +38 -144
  86. package/src/goals/state.ts +36 -7
  87. package/src/goals/tools/goal-tool.ts +15 -172
  88. package/src/hooks/skill-state.ts +39 -18
  89. package/src/internal-urls/docs-index.generated.ts +5 -4
  90. package/src/internal-urls/memory-protocol.ts +3 -2
  91. package/src/main.ts +2 -3
  92. package/src/memories/index.ts +2 -1
  93. package/src/memory-backend/local-backend.ts +14 -6
  94. package/src/modes/components/hook-selector.ts +156 -1
  95. package/src/modes/components/settings-selector.ts +5 -12
  96. package/src/modes/components/skill-hud/render.ts +4 -0
  97. package/src/modes/components/status-line/segments.ts +5 -16
  98. package/src/modes/components/status-line/types.ts +0 -3
  99. package/src/modes/components/status-line.ts +0 -6
  100. package/src/modes/controllers/command-controller.ts +27 -4
  101. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  102. package/src/modes/controllers/input-controller.ts +0 -15
  103. package/src/modes/controllers/selector-controller.ts +4 -11
  104. package/src/modes/interactive-mode.ts +18 -219
  105. package/src/modes/theme/defaults/dark-poimandres.json +0 -1
  106. package/src/modes/theme/defaults/light-poimandres.json +0 -1
  107. package/src/modes/theme/theme.ts +0 -6
  108. package/src/modes/types.ts +1 -7
  109. package/src/modes/utils/context-usage.ts +66 -17
  110. package/src/prompts/agents/architect.md +3 -0
  111. package/src/prompts/agents/executor.md +2 -0
  112. package/src/prompts/agents/frontmatter.md +1 -0
  113. package/src/prompts/goals/goal-continuation.md +1 -4
  114. package/src/prompts/goals/goal-mode-active.md +3 -5
  115. package/src/prompts/system/subagent-system-prompt.md +6 -0
  116. package/src/prompts/system/system-prompt.md +5 -7
  117. package/src/prompts/tools/goal.md +4 -4
  118. package/src/prompts/tools/skill.md +28 -0
  119. package/src/prompts/tools/task.md +3 -0
  120. package/src/sdk.ts +51 -11
  121. package/src/session/agent-session.ts +222 -21
  122. package/src/session/contribution-prep.ts +320 -0
  123. package/src/session/session-manager.ts +9 -1
  124. package/src/setup/model-onboarding-guidance.ts +6 -3
  125. package/src/setup/provider-onboarding.ts +177 -16
  126. package/src/skill-state/active-state.ts +188 -25
  127. package/src/skill-state/deep-interview-mutation-guard.ts +72 -21
  128. package/src/skill-state/initial-phase.ts +17 -0
  129. package/src/skill-state/workflow-hud.ts +23 -5
  130. package/src/skill-state/workflow-state-contract.ts +121 -0
  131. package/src/slash-commands/builtin-registry.ts +75 -25
  132. package/src/slash-commands/helpers/context-report.ts +123 -13
  133. package/src/task/agents.ts +1 -0
  134. package/src/task/commands.ts +1 -5
  135. package/src/task/executor.ts +9 -1
  136. package/src/task/index.ts +91 -4
  137. package/src/task/types.ts +6 -0
  138. package/src/tools/ask.ts +2 -0
  139. package/src/tools/gh.ts +212 -2
  140. package/src/tools/index.ts +25 -6
  141. package/src/tools/skill.ts +153 -0
  142. package/src/utils/changelog.ts +67 -44
  143. package/dist/types/commands/gjc-runtime-bridge.d.ts +0 -30
  144. package/dist/types/commands/question.d.ts +0 -7
  145. package/dist/types/modes/loop-limit.d.ts +0 -22
  146. package/src/commands/gjc-runtime-bridge.ts +0 -227
  147. package/src/commands/question.ts +0 -12
  148. package/src/modes/loop-limit.ts +0 -140
  149. package/src/prompts/commands/orchestrate.md +0 -49
  150. package/src/prompts/goals/goal-budget-limit.md +0 -16
  151. package/src/prompts/tools/create-goal.md +0 -3
  152. package/src/prompts/tools/get-goal.md +0 -3
  153. package/src/prompts/tools/update-goal.md +0 -3
@@ -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.compat) missing.push("--compat");
203
- if (!flags.provider) missing.push("--provider");
204
- if (!flags.baseUrl) missing.push("--base-url");
205
- if (!flags.apiKeyEnv) missing.push("--api-key-env");
206
- if (!flags.model || flags.model.length === 0) missing.push("--model");
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(`Missing required provider setup option(s): ${missing.join(", ")}`);
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
- providerId: flags.provider!,
213
- baseUrl: flags.baseUrl!,
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 an OpenAI-compatible or Anthropic-compatible API provider
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 { syncSkillActiveState } from "../skill-state/active-state";
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 private GJC deep-interview workflow commands";
5
+ static description = "Run native GJC deep-interview workflow";
7
6
  static strict = false;
8
- static examples = ["$ gjc deep-interview --help"];
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 cwd = process.cwd();
12
- const result = await runGjcRuntimeBridgeWithHudSidecar("deep-interview", this.argv, {
13
- cwd,
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
  }
@@ -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 (launchDefaultTmuxIfNeeded({ parsed: launchParsed, rawArgs: launch.args, cwd: launch.cwd })) return;
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
  }
@@ -1,31 +1,19 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
- import { syncSkillActiveState } from "../skill-state/active-state";
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 private GJC RALPLAN workflow commands";
5
+ static description = "Run native GJC RALPLAN consensus planning workflow";
7
6
  static strict = false;
8
- static examples = ["$ gjc ralplan --help"];
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 cwd = process.cwd();
12
- const result = await runGjcRuntimeBridgeWithHudSidecar("ralplan", this.argv, {
13
- cwd,
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
+ }
@@ -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"],
@@ -1,12 +1,23 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
- import { runBridgedRuntimeEndpoint } from "./gjc-runtime-bridge";
2
+ import { runNativeStateCommand } from "../gjc-runtime/state-runtime";
3
3
 
4
4
  export default class State extends Command {
5
- static description = "Read or update private GJC workflow state";
5
+ static description = "Read or update GJC workflow state receipts under .gjc/state";
6
6
  static strict = false;
7
- static examples = ['$ gjc state read --input \'{"mode":"team"}\' --json'];
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 runBridgedRuntimeEndpoint("state", this.argv);
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
  }
@@ -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 commands";
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({ description: "Create team state without starting tmux panes", default: false }),
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
- : !config.apiKey && !config.apiKeyEnv && (config.auth ?? "apiKey") !== "none";
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"