@gajae-code/coding-agent 0.4.5 → 0.5.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 +43 -0
- package/dist/types/commands/harness.d.ts +3 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -2
- package/dist/types/config/model-profiles.d.ts +7 -0
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +30 -0
- package/dist/types/config/settings-schema.d.ts +4 -3
- package/dist/types/gjc-runtime/team-runtime.d.ts +0 -1
- package/dist/types/gjc-runtime/tmux-common.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +1 -1
- package/dist/types/harness-control-plane/receipt-spool.d.ts +19 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +6 -1
- package/dist/types/harness-control-plane/types.d.ts +4 -0
- package/dist/types/hindsight/mental-models.d.ts +5 -5
- package/dist/types/modes/components/model-selector.d.ts +1 -12
- package/dist/types/modes/rpc/rpc-client.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-types.d.ts +4 -1
- package/dist/types/sdk.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +2 -0
- package/dist/types/session/blob-store.d.ts +20 -1
- package/dist/types/session/session-manager.d.ts +24 -6
- package/dist/types/session/streaming-output.d.ts +3 -2
- package/dist/types/session/tool-choice-queue.d.ts +6 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +7 -0
- package/dist/types/thinking-metadata.d.ts +16 -0
- package/dist/types/thinking.d.ts +3 -12
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resolve.d.ts +0 -10
- package/dist/types/utils/tool-choice.d.ts +14 -1
- package/package.json +7 -7
- package/src/cli.ts +8 -4
- package/src/commands/harness.ts +36 -2
- package/src/commands/launch.ts +2 -2
- package/src/commands/session.ts +3 -1
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +255 -56
- package/src/config/model-resolver.ts +9 -6
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +6 -3
- package/src/coordinator-mcp/server.ts +54 -23
- package/src/cursor.ts +16 -2
- package/src/defaults/gjc/skills/team/SKILL.md +3 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +8 -2
- package/src/export/html/index.ts +13 -9
- package/src/gjc-runtime/team-runtime.ts +33 -7
- package/src/gjc-runtime/tmux-common.ts +15 -0
- package/src/gjc-runtime/tmux-sessions.ts +19 -11
- package/src/gjc-runtime/ultragoal-runtime.ts +505 -41
- package/src/gjc-runtime/workflow-manifest.generated.json +27 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -1
- package/src/harness-control-plane/owner.ts +78 -27
- package/src/harness-control-plane/receipt-spool.ts +128 -0
- package/src/harness-control-plane/state-machine.ts +27 -6
- package/src/harness-control-plane/storage.ts +23 -0
- package/src/harness-control-plane/types.ts +4 -0
- package/src/hindsight/mental-models.ts +17 -16
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/modes/components/assistant-message.ts +26 -14
- package/src/modes/components/diff.ts +97 -0
- package/src/modes/components/model-selector.ts +353 -181
- package/src/modes/components/tool-execution.ts +30 -13
- package/src/modes/controllers/selector-controller.ts +33 -42
- package/src/modes/rpc/rpc-client.ts +3 -2
- package/src/modes/rpc/rpc-mode.ts +44 -14
- package/src/modes/rpc/rpc-types.ts +5 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +10 -5
- package/src/modes/shared/agent-wire/command-validation.ts +11 -0
- package/src/sdk.ts +29 -2
- package/src/secrets/obfuscator.ts +102 -27
- package/src/session/agent-session.ts +105 -20
- package/src/session/blob-store.ts +89 -3
- package/src/session/session-manager.ts +309 -58
- package/src/session/streaming-output.ts +185 -122
- package/src/session/tool-choice-queue.ts +23 -0
- package/src/task/executor.ts +69 -6
- package/src/task/receipt.ts +5 -0
- package/src/task/render.ts +21 -1
- package/src/task/types.ts +8 -0
- package/src/thinking-metadata.ts +51 -0
- package/src/thinking.ts +26 -46
- package/src/tools/bash.ts +1 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/resolve.ts +93 -18
- package/src/utils/edit-mode.ts +1 -1
- package/src/utils/tool-choice.ts +45 -16
|
@@ -5,7 +5,7 @@ import type { WorkflowHudSummary } from "../skill-state/active-state";
|
|
|
5
5
|
import { buildTeamHudSummary as buildWorkflowTeamHudSummary } from "../skill-state/workflow-hud";
|
|
6
6
|
import { WORKFLOW_STATE_VERSION } from "../skill-state/workflow-state-contract";
|
|
7
7
|
|
|
8
|
-
import { applyGjcTmuxProfile } from "./launch-tmux";
|
|
8
|
+
import { applyGjcTmuxProfile, GJC_TMUX_LAUNCHED_ENV } from "./launch-tmux";
|
|
9
9
|
import {
|
|
10
10
|
AlreadyExistsError,
|
|
11
11
|
appendJsonl as appendJsonlAudited,
|
|
@@ -17,7 +17,12 @@ import {
|
|
|
17
17
|
writeReport,
|
|
18
18
|
writeWorkflowEnvelopeAtomic,
|
|
19
19
|
} from "./state-writer";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
buildGjcTmuxUntaggedSessionHint,
|
|
22
|
+
GJC_TMUX_PROFILE_OPTION,
|
|
23
|
+
GJC_TMUX_PROFILE_VALUE,
|
|
24
|
+
resolveGjcTmuxCommand,
|
|
25
|
+
} from "./tmux-common";
|
|
21
26
|
|
|
22
27
|
export type GjcTeamPhase = "starting" | "running" | "awaiting_integration" | "complete" | "failed" | "cancelled";
|
|
23
28
|
export type GjcTeamTaskStatus = "pending" | "blocked" | "in_progress" | "completed" | "failed";
|
|
@@ -1622,9 +1627,6 @@ async function ensureWorkerWorktree(
|
|
|
1622
1627
|
};
|
|
1623
1628
|
}
|
|
1624
1629
|
|
|
1625
|
-
export function resolveGjcTmuxCommand(env: NodeJS.ProcessEnv = process.env): string {
|
|
1626
|
-
return env.GJC_TEAM_TMUX_COMMAND?.trim() || "tmux";
|
|
1627
|
-
}
|
|
1628
1630
|
function buildTeamTmuxLeaderRequirementMessage(detail?: string): string {
|
|
1629
1631
|
const suffix = detail?.trim() ? `:${detail.trim()}` : "";
|
|
1630
1632
|
return `gjc_team_requires_tmux_leader: run \`gjc --tmux\` first, then run \`gjc team ...\` inside that tmux-backed leader session, or use \`gjc team --dry-run\` for state-only smoke tests${suffix}`;
|
|
@@ -1641,6 +1643,17 @@ function readGjcTmuxProfileValue(tmuxCommand: string, sessionName: string): stri
|
|
|
1641
1643
|
return result.stdout.toString().trim();
|
|
1642
1644
|
}
|
|
1643
1645
|
|
|
1646
|
+
function retagGjcLaunchedTmuxSession(tmuxCommand: string, sessionName: string): boolean {
|
|
1647
|
+
const result = Bun.spawnSync(
|
|
1648
|
+
[tmuxCommand, "set-option", "-t", `=${sessionName}`, GJC_TMUX_PROFILE_OPTION, GJC_TMUX_PROFILE_VALUE],
|
|
1649
|
+
{
|
|
1650
|
+
stdout: "pipe",
|
|
1651
|
+
stderr: "pipe",
|
|
1652
|
+
},
|
|
1653
|
+
);
|
|
1654
|
+
return result.exitCode === 0;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1644
1657
|
function readCurrentTmuxLeaderContext(tmuxCommand: string, env: NodeJS.ProcessEnv): GjcTmuxLeaderContext {
|
|
1645
1658
|
const paneTarget = env.TMUX_PANE?.trim();
|
|
1646
1659
|
const args = paneTarget
|
|
@@ -1652,8 +1665,21 @@ function readCurrentTmuxLeaderContext(tmuxCommand: string, env: NodeJS.ProcessEn
|
|
|
1652
1665
|
const [sessionName = "", windowIndex = ""] = sessionAndWindow.split(":");
|
|
1653
1666
|
if (!sessionName || !windowIndex || !leaderPaneId.startsWith("%"))
|
|
1654
1667
|
throw new Error(buildTeamTmuxLeaderRequirementMessage(`invalid_tmux_context:${result.stdout.toString().trim()}`));
|
|
1655
|
-
if (readGjcTmuxProfileValue(tmuxCommand, sessionName) !== GJC_TMUX_PROFILE_VALUE)
|
|
1656
|
-
|
|
1668
|
+
if (readGjcTmuxProfileValue(tmuxCommand, sessionName) !== GJC_TMUX_PROFILE_VALUE) {
|
|
1669
|
+
// Self-heal: a pane launched through `gjc --tmux` exports
|
|
1670
|
+
// GJC_TMUX_LAUNCHED=1, but the session can lose (or never receive) the
|
|
1671
|
+
// @gjc-profile user-option tag when startup attach fails mid-way or the
|
|
1672
|
+
// registry write races. That stranded-but-genuinely-GJC leader pane
|
|
1673
|
+
// previously hard-failed as unmanaged_tmux_session; re-tag it instead.
|
|
1674
|
+
const launchedByGjc = env[GJC_TMUX_LAUNCHED_ENV] === "1";
|
|
1675
|
+
const retagged = launchedByGjc && retagGjcLaunchedTmuxSession(tmuxCommand, sessionName);
|
|
1676
|
+
if (!retagged || readGjcTmuxProfileValue(tmuxCommand, sessionName) !== GJC_TMUX_PROFILE_VALUE)
|
|
1677
|
+
throw new Error(
|
|
1678
|
+
buildTeamTmuxLeaderRequirementMessage(
|
|
1679
|
+
`unmanaged_tmux_session:${sessionName} — ${buildGjcTmuxUntaggedSessionHint(tmuxCommand)}`,
|
|
1680
|
+
),
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1657
1683
|
return { sessionName, windowIndex, leaderPaneId, target: `${sessionName}:${windowIndex}` };
|
|
1658
1684
|
}
|
|
1659
1685
|
export function resolveGjcWorkerCommand(cwd = process.cwd(), env: NodeJS.ProcessEnv = process.env): string {
|
|
@@ -32,6 +32,21 @@ export function resolveGjcTmuxCommand(env: NodeJS.ProcessEnv = process.env): str
|
|
|
32
32
|
return env[GJC_TMUX_COMMAND_ENV]?.trim() || env.GJC_TEAM_TMUX_COMMAND?.trim() || "tmux";
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
export const GJC_TMUX_UNTAGGED_REASON = "gjc_tmux_session_untagged";
|
|
36
|
+
|
|
37
|
+
export function buildGjcTmuxUntaggedSessionHint(tmuxCommand: string): string {
|
|
38
|
+
return (
|
|
39
|
+
`the active multiplexer "${tmuxCommand}" lists this session but did not return GJC's ${GJC_TMUX_PROFILE_OPTION} ownership tag; ` +
|
|
40
|
+
"GJC-managed sessions and `gjc team` require a tmux provider that round-trips tmux user options. " +
|
|
41
|
+
"Alternative multiplexers such as psmux on Windows do not persist user options yet, so the Windows-native psmux path is not fully supported; " +
|
|
42
|
+
"use real tmux for GJC-managed session and team flows."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function buildGjcTmuxUntaggedSessionError(sessionName: string, tmuxCommand: string): string {
|
|
47
|
+
return `${GJC_TMUX_UNTAGGED_REASON}:${sessionName} — ${buildGjcTmuxUntaggedSessionHint(tmuxCommand)}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
35
50
|
export function sanitizeTmuxToken(value: string): string {
|
|
36
51
|
return (
|
|
37
52
|
value
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildGjcTmuxProfileCommands,
|
|
3
3
|
buildGjcTmuxSessionName,
|
|
4
|
+
buildGjcTmuxUntaggedSessionError,
|
|
4
5
|
GJC_TMUX_BRANCH_OPTION,
|
|
5
6
|
GJC_TMUX_BRANCH_SLUG_OPTION,
|
|
6
7
|
GJC_TMUX_PROFILE_OPTION,
|
|
@@ -73,17 +74,10 @@ function parseSessionLine(line: string): GjcTmuxSessionStatus | null {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
function
|
|
77
|
+
function runListSessions(format: string, env: NodeJS.ProcessEnv = process.env): string[] {
|
|
77
78
|
let output = "";
|
|
78
79
|
try {
|
|
79
|
-
output = runTmux(
|
|
80
|
-
[
|
|
81
|
-
"list-sessions",
|
|
82
|
-
"-F",
|
|
83
|
-
`#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_created}\t#{${GJC_TMUX_PROFILE_OPTION}}\t#{session_key_table}\t#{session_panes}\t#{${GJC_TMUX_BRANCH_OPTION}}\t#{${GJC_TMUX_BRANCH_SLUG_OPTION}}\t#{${GJC_TMUX_PROJECT_OPTION}}`,
|
|
84
|
-
],
|
|
85
|
-
env,
|
|
86
|
-
);
|
|
80
|
+
output = runTmux(["list-sessions", "-F", format], env);
|
|
87
81
|
} catch (error) {
|
|
88
82
|
const message = error instanceof Error ? error.message : String(error);
|
|
89
83
|
if (message.includes("no server running") || message.includes("failed to connect to server")) return [];
|
|
@@ -95,6 +89,17 @@ function listSessionLines(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
|
95
89
|
.filter(Boolean);
|
|
96
90
|
}
|
|
97
91
|
|
|
92
|
+
function listSessionLines(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
93
|
+
return runListSessions(
|
|
94
|
+
`#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_created}\t#{${GJC_TMUX_PROFILE_OPTION}}\t#{session_key_table}\t#{session_panes}\t#{${GJC_TMUX_BRANCH_OPTION}}\t#{${GJC_TMUX_BRANCH_SLUG_OPTION}}\t#{${GJC_TMUX_PROJECT_OPTION}}`,
|
|
95
|
+
env,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function listRawTmuxSessionNames(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
100
|
+
return runListSessions("#{session_name}", env).map(line => line.split("\t")[0] ?? line);
|
|
101
|
+
}
|
|
102
|
+
|
|
98
103
|
export function listGjcTmuxSessions(env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionStatus[] {
|
|
99
104
|
return listSessionLines(env)
|
|
100
105
|
.map(parseSessionLine)
|
|
@@ -114,8 +119,11 @@ export function findGjcTmuxSessionByBranch(
|
|
|
114
119
|
|
|
115
120
|
export function statusGjcTmuxSession(sessionName: string, env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionStatus {
|
|
116
121
|
const session = listGjcTmuxSessions(env).find(candidate => candidate.name === sessionName);
|
|
117
|
-
if (
|
|
118
|
-
|
|
122
|
+
if (session) return session;
|
|
123
|
+
if (listRawTmuxSessionNames(env).includes(sessionName)) {
|
|
124
|
+
throw new Error(buildGjcTmuxUntaggedSessionError(sessionName, resolveGjcTmuxCommand(env)));
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`gjc_tmux_session_not_found:${sessionName}`);
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
export function createGjcTmuxSession(env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionStatus {
|