@nseng-ai/ccc 0.1.1
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/package.json +48 -0
- package/src/api/handlers.ts +75 -0
- package/src/api/index.ts +11 -0
- package/src/cmux/branch-slug.ts +174 -0
- package/src/cmux/claude-plan-tab.ts +124 -0
- package/src/cmux/command-surfaces.ts +51 -0
- package/src/cmux/dispatch-from-trunk.ts +177 -0
- package/src/cmux/dispatch-prompt.ts +459 -0
- package/src/cmux/objective-sidebar.ts +373 -0
- package/src/cmux/prompt-file.ts +34 -0
- package/src/cmux/sidebar.ts +386 -0
- package/src/cmux/slot-checkout.ts +46 -0
- package/src/cmux/slot-dispatch-plan.ts +560 -0
- package/src/cmux/slot-open-branch.ts +241 -0
- package/src/cmux/slot.ts +126 -0
- package/src/cmux/workspace-summary.ts +222 -0
- package/src/cmux/worktree-description.ts +87 -0
- package/src/ns/autobranch/checkpoint.ts +35 -0
- package/src/ns/autobranch/flow.ts +18 -0
- package/src/ns/autoslot-presentation.ts +33 -0
- package/src/ns/autoslot.ts +2 -0
- package/src/ns/cli-command-io.ts +23 -0
- package/src/ns/cli.ts +186 -0
- package/src/ns/land.ts +12 -0
- package/src/ns/trunk-pull.ts +2 -0
- package/src/pi/claude-plan-tab.ts +32 -0
- package/src/pi/command-backed-skills.ts +7 -0
- package/src/pi/dispatch-from-trunk.ts +41 -0
- package/src/pi/dispatch-prompt.ts +41 -0
- package/src/pi/extension.ts +23 -0
- package/src/pi/index.ts +11 -0
- package/src/pi/sidebar.ts +58 -0
- package/src/pi/slot-dispatch-plan.ts +70 -0
- package/src/pi/slot-open-branch.ts +39 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FlowAutobranchCheckpointInput,
|
|
3
|
+
FlowAutobranchCheckpointResult,
|
|
4
|
+
FlowAutobranchFileStat,
|
|
5
|
+
FlowAutobranchRequest,
|
|
6
|
+
} from "@nseng-ai/flow/api";
|
|
7
|
+
import { createFlowAutobranchCheckpointFlow } from "@nseng-ai/flow/api";
|
|
8
|
+
|
|
9
|
+
export type AutobranchFlowInput = FlowAutobranchCheckpointInput;
|
|
10
|
+
export type AutobranchFlowResult = FlowAutobranchCheckpointResult;
|
|
11
|
+
export type FileStat = FlowAutobranchFileStat;
|
|
12
|
+
export type ParsedAutobranchArgs = FlowAutobranchRequest;
|
|
13
|
+
|
|
14
|
+
export async function createAutobranchCheckpointFlow(
|
|
15
|
+
input: AutobranchFlowInput,
|
|
16
|
+
): Promise<AutobranchFlowResult> {
|
|
17
|
+
return await createFlowAutobranchCheckpointFlow(input);
|
|
18
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// CCC-local facade for the `autoslot` workflow's durable outcomes.
|
|
2
|
+
//
|
|
3
|
+
// `autoslot` (autobranch + slot checkout) is orchestrated in CCC and reports typed settled facts here,
|
|
4
|
+
// while the generic finite block layout now lives in `@nseng-ai/foundation/cli-theme` because the repeated shape was
|
|
5
|
+
// proven across Flow and CCC. This module keeps autoslot's domain-local type name and owns the mapping
|
|
6
|
+
// from CCC outcome facts to that shared layout.
|
|
7
|
+
|
|
8
|
+
import type { Caps } from "@nseng-ai/clinkr";
|
|
9
|
+
import { renderResultBlock } from "@nseng-ai/foundation/cli-theme";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The visual intent of an autoslot outcome. Distinct from the `NsCommandIo` notify level (which owns
|
|
13
|
+
* stdout/stderr routing and exit-code flipping): a declined guardrail renders `refusal` (warn) even
|
|
14
|
+
* when it is notified at `error` level to flip the exit code (house-style §7.3).
|
|
15
|
+
*/
|
|
16
|
+
export type AutoslotResultKind = "success" | "refusal" | "failure";
|
|
17
|
+
|
|
18
|
+
export interface AutoslotResultBlock {
|
|
19
|
+
kind: AutoslotResultKind;
|
|
20
|
+
/** Leading one-line summary (already-phrased prose); rendered bold + intent-painted with a glyph. */
|
|
21
|
+
headline: string;
|
|
22
|
+
/** The working directory the workflow operated in, shown as dimmed plumbing evidence. */
|
|
23
|
+
cwd: string;
|
|
24
|
+
/** Domain-authored detail (slot target / skip reason / failure cause) at normal weight. */
|
|
25
|
+
body?: string;
|
|
26
|
+
/** Optional normal-weight "what to do next" line (e.g. the copyable `ns slot co <branch>`). */
|
|
27
|
+
guidance?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Render an autoslot result block to a string, styled and degraded for `caps`. */
|
|
31
|
+
export function renderAutoslotResultBlock(caps: Caps, input: AutoslotResultBlock): string {
|
|
32
|
+
return renderResultBlock(caps, input);
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCliCommandIo,
|
|
3
|
+
type CliCommandIoInput,
|
|
4
|
+
type CliCommandIoOptions,
|
|
5
|
+
} from "@nseng-ai/ns/kernel/command-io";
|
|
6
|
+
import type { NsCommandIo } from "@nseng-ai/ns/kernel/sdk";
|
|
7
|
+
|
|
8
|
+
/** Minimal CLI stream/callback surface that CCC standalone commands adapt to NsCommandIo. */
|
|
9
|
+
export type CccCliCommandIoInput = CliCommandIoInput;
|
|
10
|
+
|
|
11
|
+
export type CccCliCommandIoOptions = CliCommandIoOptions;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* CCC edge adapter mapping CLI stdout/stderr/onOutput callbacks onto an NsCommandIo.
|
|
15
|
+
* The implementation lives in the kernel because command I/O is an intrinsic
|
|
16
|
+
* SDK service, not CCC orchestration behavior.
|
|
17
|
+
*/
|
|
18
|
+
export function createCccCliCommandIo(
|
|
19
|
+
input: CccCliCommandIoInput,
|
|
20
|
+
options: CccCliCommandIoOptions = {},
|
|
21
|
+
): NsCommandIo {
|
|
22
|
+
return createCliCommandIo(input, options);
|
|
23
|
+
}
|
package/src/ns/cli.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { ClinkrGroup, failure, negative, ok, type ClinkrExit } from "@nseng-ai/clinkr";
|
|
6
|
+
import { defineCli, type CliEntrypointDeps } from "@nseng-ai/foundation/cli-runtime";
|
|
7
|
+
import { NodeCommandExecApi } from "@nseng-ai/foundation/exec";
|
|
8
|
+
import type { CommandExecApi } from "@nseng-ai/foundation/command";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
commitAutobranchCheckpointMessage,
|
|
12
|
+
prepareAutobranchCheckpointMessage,
|
|
13
|
+
} from "./autobranch/checkpoint.ts";
|
|
14
|
+
import {
|
|
15
|
+
createFlowAutobranchCheckpointFlow,
|
|
16
|
+
type FlowAutobranchCheckpointInput,
|
|
17
|
+
type FlowAutobranchRequest,
|
|
18
|
+
} from "@nseng-ai/flow/api";
|
|
19
|
+
import {
|
|
20
|
+
applyCmuxWorkspaceSummaryCommand,
|
|
21
|
+
cmuxWorkspaceSummaryRequestSchema,
|
|
22
|
+
cmuxWorkspaceSummaryResultSchema,
|
|
23
|
+
renderCmuxWorkspaceSummaryHuman,
|
|
24
|
+
} from "../cmux/workspace-summary.ts";
|
|
25
|
+
|
|
26
|
+
export const AUTOBRANCH_SUMMARY =
|
|
27
|
+
"Create a Graphite branch from dirty worktree changes or the latest unpushed commit.";
|
|
28
|
+
|
|
29
|
+
type AutobranchSeamOverrides = Partial<
|
|
30
|
+
Pick<
|
|
31
|
+
FlowAutobranchCheckpointInput,
|
|
32
|
+
"prepareCheckpointMessage" | "commitPreparedCheckpointMessage" | "readFile" | "stat" | "now"
|
|
33
|
+
>
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
export interface CccCliDeps extends Pick<CliEntrypointDeps, "cwd" | "env" | "stdout" | "stderr"> {
|
|
37
|
+
commands?: CommandExecApi;
|
|
38
|
+
autobranch?: AutobranchSeamOverrides;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CccCliContext {
|
|
42
|
+
commands: CommandExecApi;
|
|
43
|
+
cwd: string;
|
|
44
|
+
env: Record<string, string | undefined>;
|
|
45
|
+
stdout: (text: string) => void;
|
|
46
|
+
stderr: (text: string) => void;
|
|
47
|
+
autobranch?: AutobranchSeamOverrides;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const autobranchRequestSchema = z.object({
|
|
51
|
+
slug: z
|
|
52
|
+
.string()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Branch slug to use instead of deriving one from the worktree or latest commit."),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
type AutobranchRequest = z.infer<typeof autobranchRequestSchema>;
|
|
58
|
+
|
|
59
|
+
const autobranchSuccessSchema = z.object({
|
|
60
|
+
summary: z.string(),
|
|
61
|
+
warnings: z.array(z.string()),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const autobranchErrorDataSchema = z.object({
|
|
65
|
+
outcome: z.enum(["refusal", "failure"]),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const autobranchResultSchema = z.union([autobranchSuccessSchema, autobranchErrorDataSchema]);
|
|
69
|
+
|
|
70
|
+
type AutobranchResult = z.infer<typeof autobranchResultSchema>;
|
|
71
|
+
type AutobranchErrorData = z.infer<typeof autobranchErrorDataSchema>;
|
|
72
|
+
|
|
73
|
+
const entry = defineCli<CccCliContext, CccCliDeps, undefined>({
|
|
74
|
+
metaUrl: import.meta.url,
|
|
75
|
+
runtime: "typescript",
|
|
76
|
+
description: "CCC repo orchestration tools.",
|
|
77
|
+
prepareRun: ({ deps, cwd, env, stdout, stderr }) => {
|
|
78
|
+
const resolvedStdout = deps.stdout ?? stdout;
|
|
79
|
+
const resolvedStderr = deps.stderr ?? stderr;
|
|
80
|
+
const context: CccCliContext = {
|
|
81
|
+
commands: deps.commands ?? new NodeCommandExecApi(),
|
|
82
|
+
cwd: deps.cwd ?? cwd,
|
|
83
|
+
env: deps.env ?? env,
|
|
84
|
+
stdout: resolvedStdout,
|
|
85
|
+
stderr: resolvedStderr,
|
|
86
|
+
...(deps.autobranch === undefined ? {} : { autobranch: deps.autobranch }),
|
|
87
|
+
};
|
|
88
|
+
return { type: "run", context, buildState: undefined };
|
|
89
|
+
},
|
|
90
|
+
configureCli: ({ root }) => {
|
|
91
|
+
const execGroup = new ClinkrGroup<CccCliContext>({
|
|
92
|
+
name: "exec",
|
|
93
|
+
description: "Run hidden deterministic CCC operations for agents.",
|
|
94
|
+
isHidden: true,
|
|
95
|
+
});
|
|
96
|
+
execGroup.command({
|
|
97
|
+
name: "cmux-workspace-summary",
|
|
98
|
+
summary: "Apply generated cmux workspace title and description fields.",
|
|
99
|
+
description: "Apply generated cmux workspace title and description fields.",
|
|
100
|
+
schema: cmuxWorkspaceSummaryRequestSchema,
|
|
101
|
+
resultSchema: cmuxWorkspaceSummaryResultSchema,
|
|
102
|
+
handler: handleCmuxWorkspaceSummary,
|
|
103
|
+
renderHuman: renderCmuxWorkspaceSummaryHuman,
|
|
104
|
+
});
|
|
105
|
+
execGroup.command({
|
|
106
|
+
name: "autobranch",
|
|
107
|
+
summary: AUTOBRANCH_SUMMARY,
|
|
108
|
+
description: `Create a Graphite branch using \`gt create\` from dirty worktree changes or from the latest eligible unpushed commit.
|
|
109
|
+
|
|
110
|
+
Dirty worktree mode stashes pending changes, creates a Graphite branch, restores the stash, and creates a checkpoint commit. Clean worktree mode moves the latest eligible unpushed non-merge commit onto a new Graphite branch using recovery-branch verification.`,
|
|
111
|
+
schema: autobranchRequestSchema,
|
|
112
|
+
resultSchema: autobranchResultSchema,
|
|
113
|
+
handler: handleAutobranch,
|
|
114
|
+
renderHuman: renderAutobranch,
|
|
115
|
+
});
|
|
116
|
+
root.group(execGroup);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export function buildCli(): ClinkrGroup<CccCliContext> {
|
|
121
|
+
return entry.buildCli(undefined);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function runCli(args: readonly string[], deps: CccCliDeps = {}): Promise<number> {
|
|
125
|
+
return await entry.run(args, deps);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function handleCmuxWorkspaceSummary(
|
|
129
|
+
ctx: CccCliContext,
|
|
130
|
+
request: z.output<typeof cmuxWorkspaceSummaryRequestSchema>,
|
|
131
|
+
) {
|
|
132
|
+
return applyCmuxWorkspaceSummaryCommand({
|
|
133
|
+
request,
|
|
134
|
+
commands: ctx.commands,
|
|
135
|
+
cwd: ctx.cwd,
|
|
136
|
+
env: ctx.env,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function handleAutobranch(
|
|
141
|
+
ctx: CccCliContext,
|
|
142
|
+
request: AutobranchRequest,
|
|
143
|
+
): Promise<ClinkrExit<AutobranchResult>> {
|
|
144
|
+
const args: FlowAutobranchRequest = request.slug === undefined ? {} : { slug: request.slug };
|
|
145
|
+
const autobranch = ctx.autobranch ?? {};
|
|
146
|
+
const result = await createFlowAutobranchCheckpointFlow({
|
|
147
|
+
cwd: ctx.cwd,
|
|
148
|
+
args,
|
|
149
|
+
exec: (command, commandArgs, timeout) =>
|
|
150
|
+
ctx.commands.exec(command, commandArgs, { cwd: ctx.cwd, timeout, env: ctx.env }),
|
|
151
|
+
prepareCheckpointMessage:
|
|
152
|
+
autobranch.prepareCheckpointMessage ??
|
|
153
|
+
((snapshot) => prepareAutobranchCheckpointMessage(snapshot, ctx.env)),
|
|
154
|
+
commitPreparedCheckpointMessage:
|
|
155
|
+
autobranch.commitPreparedCheckpointMessage ??
|
|
156
|
+
((message) =>
|
|
157
|
+
commitAutobranchCheckpointMessage(
|
|
158
|
+
(command, commandArgs, commandCwd, timeout) =>
|
|
159
|
+
ctx.commands.exec(command, commandArgs, { cwd: commandCwd, timeout, env: ctx.env }),
|
|
160
|
+
ctx.cwd,
|
|
161
|
+
message,
|
|
162
|
+
)),
|
|
163
|
+
...(autobranch.readFile === undefined ? {} : { readFile: autobranch.readFile }),
|
|
164
|
+
...(autobranch.stat === undefined ? {} : { stat: autobranch.stat }),
|
|
165
|
+
...(autobranch.now === undefined ? {} : { now: autobranch.now }),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (!result.ok) {
|
|
169
|
+
const data: AutobranchErrorData = { outcome: result.outcome };
|
|
170
|
+
if (result.outcome === "refusal") {
|
|
171
|
+
return negative(result.error, { data, human: result.error });
|
|
172
|
+
}
|
|
173
|
+
return failure("autobranch-failed", result.error, data);
|
|
174
|
+
}
|
|
175
|
+
for (const warning of result.warnings) {
|
|
176
|
+
ctx.stderr(`${warning.trimEnd()}\n`);
|
|
177
|
+
}
|
|
178
|
+
return ok({ summary: result.summary, warnings: result.warnings });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function renderAutobranch(result: AutobranchResult): string {
|
|
182
|
+
if (!("summary" in result)) return result.outcome;
|
|
183
|
+
return result.summary;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
await entry.runIfMain({ isImportMetaMain: import.meta.main });
|
package/src/ns/land.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
ExecResult,
|
|
3
|
+
ExtensionMode,
|
|
4
|
+
LandCliConfirmPrompt,
|
|
5
|
+
LandCommandContext,
|
|
6
|
+
LandCliInput,
|
|
7
|
+
LandExtensionAPI,
|
|
8
|
+
NotifyLevel,
|
|
9
|
+
PrintOutput,
|
|
10
|
+
ValidPullRequestView,
|
|
11
|
+
} from "@nseng-ai/flow/api";
|
|
12
|
+
export { parsePullRequestView, registerLandCommand, runLandCli } from "@nseng-ai/flow/api";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { registerCommandWithImmediateAck } from "@nseng-ai/pi/commands/ack";
|
|
2
|
+
import {
|
|
3
|
+
CCC_CLAUDE_PLAN_TAB_COMMAND_NAME,
|
|
4
|
+
handleCccClaudePlanTab,
|
|
5
|
+
type PromptFileOptions,
|
|
6
|
+
resolvePromptFileOptions,
|
|
7
|
+
} from "../api/handlers.ts";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
11
|
+
|
|
12
|
+
const COMMAND_NAME = CCC_CLAUDE_PLAN_TAB_COMMAND_NAME;
|
|
13
|
+
const PROMPT_DIR = join(homedir(), ".pi", "agent", "ccc-claude-plan-tab-prompts");
|
|
14
|
+
|
|
15
|
+
export function registerCccClaudePlanTabCommand(
|
|
16
|
+
pi: ExtensionAPI,
|
|
17
|
+
options: PromptFileOptions = {},
|
|
18
|
+
): void {
|
|
19
|
+
const promptOptions = resolvePromptFileOptions(options, PROMPT_DIR);
|
|
20
|
+
registerCommandWithImmediateAck({
|
|
21
|
+
host: pi,
|
|
22
|
+
commandName: COMMAND_NAME,
|
|
23
|
+
commandDefinition: {
|
|
24
|
+
description:
|
|
25
|
+
"Open a new cmux tab running Claude Code in plan mode, seeded with the provided prompt or last assistant message.",
|
|
26
|
+
argumentHint: "[seed prompt]",
|
|
27
|
+
handler: async (args, ctx) => {
|
|
28
|
+
await handleCccClaudePlanTab({ pi, ctx, args, promptOptions });
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { specializedCommandBackedSkillsFromSpecs } from "@nseng-ai/foundation/command";
|
|
2
|
+
|
|
3
|
+
import { CCC_SIDEBAR_BRANCH_STATE_SUMMARY_COMMAND_NAME } from "../api/handlers.ts";
|
|
4
|
+
|
|
5
|
+
export const cccCommandBackedSkillRegistrations = specializedCommandBackedSkillsFromSpecs([
|
|
6
|
+
{ skillName: "ccc-sidebar", surface: CCC_SIDEBAR_BRANCH_STATE_SUMMARY_COMMAND_NAME },
|
|
7
|
+
]);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { optionalEntry } from "@nseng-ai/foundation/primitives";
|
|
2
|
+
import {
|
|
3
|
+
makeCommandProgressNotifier,
|
|
4
|
+
registerCommandWithImmediateAck,
|
|
5
|
+
} from "@nseng-ai/pi/commands/ack";
|
|
6
|
+
import {
|
|
7
|
+
CCC_WORKSPACE_DISPATCH_FROM_TRUNK_COMMAND_NAME,
|
|
8
|
+
handleCccSlotDispatchFromTrunk,
|
|
9
|
+
resolveDispatchPromptPayloadOptions,
|
|
10
|
+
type DispatchPromptPayloadOptions,
|
|
11
|
+
} from "../api/handlers.ts";
|
|
12
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
13
|
+
|
|
14
|
+
const COMMAND_NAME = CCC_WORKSPACE_DISPATCH_FROM_TRUNK_COMMAND_NAME;
|
|
15
|
+
|
|
16
|
+
export function registerCccSlotDispatchFromTrunkCommand(
|
|
17
|
+
pi: ExtensionAPI,
|
|
18
|
+
options: DispatchPromptPayloadOptions = {},
|
|
19
|
+
): void {
|
|
20
|
+
const payloadOptions = resolveDispatchPromptPayloadOptions(options);
|
|
21
|
+
registerCommandWithImmediateAck({
|
|
22
|
+
host: pi,
|
|
23
|
+
commandName: COMMAND_NAME,
|
|
24
|
+
commandDefinition: {
|
|
25
|
+
description:
|
|
26
|
+
"Create a Graphite-tracked branch from trunk/main and launch it in a new cmux workspace.",
|
|
27
|
+
argumentHint: "<task>",
|
|
28
|
+
handler: async (args, ctx) => {
|
|
29
|
+
const notifyProgress = makeCommandProgressNotifier({ host: pi, ctx });
|
|
30
|
+
await handleCccSlotDispatchFromTrunk({
|
|
31
|
+
pi,
|
|
32
|
+
payloadOptions,
|
|
33
|
+
args,
|
|
34
|
+
ctx,
|
|
35
|
+
...optionalEntry("slotClient", options.slotClient),
|
|
36
|
+
notifyProgress,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { optionalEntry } from "@nseng-ai/foundation/primitives";
|
|
2
|
+
import {
|
|
3
|
+
makeCommandProgressNotifier,
|
|
4
|
+
registerCommandWithImmediateAck,
|
|
5
|
+
} from "@nseng-ai/pi/commands/ack";
|
|
6
|
+
import {
|
|
7
|
+
CCC_WORKSPACE_DISPATCH_PROMPT_COMMAND_NAME,
|
|
8
|
+
handleCccSlotDispatchPrompt,
|
|
9
|
+
type DispatchPromptPayloadOptions,
|
|
10
|
+
resolveDispatchPromptPayloadOptions,
|
|
11
|
+
} from "../api/handlers.ts";
|
|
12
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
13
|
+
|
|
14
|
+
const COMMAND_NAME = CCC_WORKSPACE_DISPATCH_PROMPT_COMMAND_NAME;
|
|
15
|
+
|
|
16
|
+
export function registerCccSlotDispatchPromptCommand(
|
|
17
|
+
pi: ExtensionAPI,
|
|
18
|
+
options: DispatchPromptPayloadOptions = {},
|
|
19
|
+
): void {
|
|
20
|
+
const payloadOptions = resolveDispatchPromptPayloadOptions(options);
|
|
21
|
+
registerCommandWithImmediateAck({
|
|
22
|
+
host: pi,
|
|
23
|
+
commandName: COMMAND_NAME,
|
|
24
|
+
commandDefinition: {
|
|
25
|
+
description:
|
|
26
|
+
"Create a Graphite-tracked branch and dispatch a prompt in a new cmux workspace.",
|
|
27
|
+
argumentHint: "<prompt>",
|
|
28
|
+
handler: async (args, ctx) => {
|
|
29
|
+
const notifyProgress = makeCommandProgressNotifier({ host: pi, ctx });
|
|
30
|
+
await handleCccSlotDispatchPrompt({
|
|
31
|
+
pi,
|
|
32
|
+
payloadOptions,
|
|
33
|
+
...optionalEntry("slotClient", options.slotClient),
|
|
34
|
+
args,
|
|
35
|
+
ctx,
|
|
36
|
+
notifyProgress,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
2
|
+
import { registerCccClaudePlanTabCommand } from "./claude-plan-tab.ts";
|
|
3
|
+
import { registerCccSlotDispatchFromTrunkCommand } from "./dispatch-from-trunk.ts";
|
|
4
|
+
import { registerCccSlotDispatchPromptCommand } from "./dispatch-prompt.ts";
|
|
5
|
+
import { createCccSidebarControllerWithPiWiring, registerCccSidebarCommands } from "./sidebar.ts";
|
|
6
|
+
import {
|
|
7
|
+
registerCccSlotDispatchPlanCommand,
|
|
8
|
+
registerCccSurfaceDispatchPlanCommand,
|
|
9
|
+
} from "./slot-dispatch-plan.ts";
|
|
10
|
+
import { registerCccSlotOpenBranchCommand } from "./slot-open-branch.ts";
|
|
11
|
+
|
|
12
|
+
export default function registerCccPiExtension(pi: ExtensionAPI): void {
|
|
13
|
+
const sidebarController = createCccSidebarControllerWithPiWiring(pi);
|
|
14
|
+
registerCccSidebarCommands(pi, sidebarController);
|
|
15
|
+
registerCccSlotDispatchPlanCommand(pi);
|
|
16
|
+
registerCccSurfaceDispatchPlanCommand(pi);
|
|
17
|
+
registerCccSlotOpenBranchCommand(pi);
|
|
18
|
+
registerCccSlotDispatchPromptCommand(pi);
|
|
19
|
+
registerCccSlotDispatchFromTrunkCommand(pi);
|
|
20
|
+
registerCccClaudePlanTabCommand(pi);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { registerCccPiExtension };
|
package/src/pi/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { default, registerCccPiExtension } from "./extension.ts";
|
|
2
|
+
export { cccCommandBackedSkillRegistrations } from "./command-backed-skills.ts";
|
|
3
|
+
export { registerCccClaudePlanTabCommand } from "./claude-plan-tab.ts";
|
|
4
|
+
export { registerCccSlotDispatchFromTrunkCommand } from "./dispatch-from-trunk.ts";
|
|
5
|
+
export { registerCccSlotDispatchPromptCommand } from "./dispatch-prompt.ts";
|
|
6
|
+
export {
|
|
7
|
+
registerCccSlotDispatchPlanCommand,
|
|
8
|
+
registerCccSurfaceDispatchPlanCommand,
|
|
9
|
+
} from "./slot-dispatch-plan.ts";
|
|
10
|
+
export { registerCccSlotOpenBranchCommand } from "./slot-open-branch.ts";
|
|
11
|
+
export { registerCccSidebarCommands, createCccSidebarControllerWithPiWiring } from "./sidebar.ts";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { registerCommandWithImmediateAck } from "@nseng-ai/pi/commands/ack";
|
|
2
|
+
import { expandRepoSkillBlock } from "@nseng-ai/pi/skills/expansion";
|
|
3
|
+
import {
|
|
4
|
+
CCC_SIDEBAR_BRANCH_STATE_SUMMARY_COMMAND_NAME,
|
|
5
|
+
CCC_SIDEBAR_OBJECTIVE_SUMMARY_COMMAND_NAME,
|
|
6
|
+
CCC_SIDEBAR_SESSION_SUMMARY_COMMAND_NAME,
|
|
7
|
+
createCccSidebarController,
|
|
8
|
+
type CccSidebarController,
|
|
9
|
+
type ObjectiveSidebarHandlerOptions,
|
|
10
|
+
} from "../api/handlers.ts";
|
|
11
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
12
|
+
|
|
13
|
+
const SESSION_SIDEBAR_COMMAND_NAME = CCC_SIDEBAR_SESSION_SUMMARY_COMMAND_NAME;
|
|
14
|
+
const BRANCH_STATE_SIDEBAR_COMMAND_NAME = CCC_SIDEBAR_BRANCH_STATE_SUMMARY_COMMAND_NAME;
|
|
15
|
+
const OBJECTIVE_SIDEBAR_COMMAND_NAME = CCC_SIDEBAR_OBJECTIVE_SUMMARY_COMMAND_NAME;
|
|
16
|
+
|
|
17
|
+
export function registerCccSidebarCommands(
|
|
18
|
+
pi: ExtensionAPI,
|
|
19
|
+
controller: CccSidebarController,
|
|
20
|
+
): void {
|
|
21
|
+
registerCommandWithImmediateAck({
|
|
22
|
+
host: pi,
|
|
23
|
+
commandName: SESSION_SIDEBAR_COMMAND_NAME,
|
|
24
|
+
commandDefinition: {
|
|
25
|
+
description: "Summarize this Pi session into the caller cmux sidebar.",
|
|
26
|
+
handler: async (_args, ctx) => controller.handleSessionCommand(ctx),
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
registerCommandWithImmediateAck({
|
|
31
|
+
host: pi,
|
|
32
|
+
commandName: BRANCH_STATE_SIDEBAR_COMMAND_NAME,
|
|
33
|
+
commandDefinition: {
|
|
34
|
+
description:
|
|
35
|
+
"Summarize the current branch state versus its parent into the caller cmux sidebar.",
|
|
36
|
+
handler: async (_args, ctx) => controller.handleBranchStateCommand(ctx),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
registerCommandWithImmediateAck({
|
|
41
|
+
host: pi,
|
|
42
|
+
commandName: OBJECTIVE_SIDEBAR_COMMAND_NAME,
|
|
43
|
+
commandDefinition: {
|
|
44
|
+
description: "Format Objective overview into the caller cmux sidebar.",
|
|
45
|
+
argumentHint: "<slug or path>",
|
|
46
|
+
handler: async (args, ctx) => controller.handleObjectiveCommand(args, ctx),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createCccSidebarControllerWithPiWiring(pi: ExtensionAPI): CccSidebarController {
|
|
52
|
+
const objectiveSidebarOptions: ObjectiveSidebarHandlerOptions = {
|
|
53
|
+
expandSkillBlock: async (cwd, skillName) => expandRepoSkillBlock({ cwd, skillName }),
|
|
54
|
+
};
|
|
55
|
+
const controller = createCccSidebarController(pi, objectiveSidebarOptions);
|
|
56
|
+
pi.on("agent_end", controller.onAgentEnd);
|
|
57
|
+
return controller;
|
|
58
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
makeCommandProgressNotifier,
|
|
3
|
+
registerCommandWithImmediateAck,
|
|
4
|
+
} from "@nseng-ai/pi/commands/ack";
|
|
5
|
+
import { formatImplBranchContextCommand } from "@nseng-ai/branch-context/pi";
|
|
6
|
+
import {
|
|
7
|
+
CCC_SURFACE_DISPATCH_PLAN_COMMAND_NAME,
|
|
8
|
+
CCC_WORKSPACE_DISPATCH_PLAN_COMMAND_NAME,
|
|
9
|
+
handleCccSlotDispatchPlan,
|
|
10
|
+
type CccSlotDispatchPlanOptions,
|
|
11
|
+
type DispatchPlanConfig,
|
|
12
|
+
} from "../api/handlers.ts";
|
|
13
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
14
|
+
|
|
15
|
+
const WORKSPACE_COMMAND_NAME = CCC_WORKSPACE_DISPATCH_PLAN_COMMAND_NAME;
|
|
16
|
+
const SURFACE_COMMAND_NAME = CCC_SURFACE_DISPATCH_PLAN_COMMAND_NAME;
|
|
17
|
+
|
|
18
|
+
const WORKSPACE_CONFIG: DispatchPlanConfig = {
|
|
19
|
+
commandName: WORKSPACE_COMMAND_NAME,
|
|
20
|
+
statusKey: WORKSPACE_COMMAND_NAME,
|
|
21
|
+
destination: "workspace",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const SURFACE_CONFIG: DispatchPlanConfig = {
|
|
25
|
+
commandName: SURFACE_COMMAND_NAME,
|
|
26
|
+
statusKey: SURFACE_COMMAND_NAME,
|
|
27
|
+
destination: "surface",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function registerCccSlotDispatchPlanCommand(
|
|
31
|
+
pi: ExtensionAPI,
|
|
32
|
+
options: CccSlotDispatchPlanOptions = {},
|
|
33
|
+
): void {
|
|
34
|
+
registerDispatchPlanCommand(pi, WORKSPACE_CONFIG, options);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function registerCccSurfaceDispatchPlanCommand(
|
|
38
|
+
pi: ExtensionAPI,
|
|
39
|
+
options: CccSlotDispatchPlanOptions = {},
|
|
40
|
+
): void {
|
|
41
|
+
registerDispatchPlanCommand(pi, SURFACE_CONFIG, options);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function registerDispatchPlanCommand(
|
|
45
|
+
pi: ExtensionAPI,
|
|
46
|
+
config: DispatchPlanConfig,
|
|
47
|
+
options: CccSlotDispatchPlanOptions,
|
|
48
|
+
): void {
|
|
49
|
+
registerCommandWithImmediateAck({
|
|
50
|
+
host: pi,
|
|
51
|
+
commandName: config.commandName,
|
|
52
|
+
commandDefinition: {
|
|
53
|
+
description:
|
|
54
|
+
"Attach the latest session-saved plan to a new Graphite-tracked branch via branch-context and launch it in a new cmux workspace.",
|
|
55
|
+
argumentHint: "[--dry-run] [--help]",
|
|
56
|
+
handler: async (rawArgs, ctx) => {
|
|
57
|
+
const notifyProgress = makeCommandProgressNotifier({ host: pi, ctx });
|
|
58
|
+
await handleCccSlotDispatchPlan({
|
|
59
|
+
pi,
|
|
60
|
+
rawArgs,
|
|
61
|
+
ctx,
|
|
62
|
+
options,
|
|
63
|
+
config,
|
|
64
|
+
notifyProgress,
|
|
65
|
+
formatBranchContextCommand: formatImplBranchContextCommand,
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
makeCommandProgressNotifier,
|
|
3
|
+
registerCommandWithImmediateAck,
|
|
4
|
+
} from "@nseng-ai/pi/commands/ack";
|
|
5
|
+
import {
|
|
6
|
+
CCC_WORKSPACE_OPEN_BRANCH_COMMAND_NAME,
|
|
7
|
+
handleCccSlotOpenBranch,
|
|
8
|
+
type CccSlotOpenBranchOptions,
|
|
9
|
+
} from "../api/handlers.ts";
|
|
10
|
+
import type { ExtensionAPI } from "@nseng-ai/capability-kit/cmux/types";
|
|
11
|
+
|
|
12
|
+
const COMMAND_NAME = CCC_WORKSPACE_OPEN_BRANCH_COMMAND_NAME;
|
|
13
|
+
|
|
14
|
+
export function registerCccSlotOpenBranchCommand(
|
|
15
|
+
pi: ExtensionAPI,
|
|
16
|
+
options: CccSlotOpenBranchOptions = {},
|
|
17
|
+
): void {
|
|
18
|
+
registerCommandWithImmediateAck({
|
|
19
|
+
host: pi,
|
|
20
|
+
commandName: COMMAND_NAME,
|
|
21
|
+
commandDefinition: {
|
|
22
|
+
description: "Open an existing Git branch in a new cmux workspace.",
|
|
23
|
+
argumentHint: "<branch>",
|
|
24
|
+
handler: async (args, ctx) => {
|
|
25
|
+
const notifyProgress = makeCommandProgressNotifier({ host: pi, ctx });
|
|
26
|
+
await handleCccSlotOpenBranch({
|
|
27
|
+
pi,
|
|
28
|
+
args,
|
|
29
|
+
ctx,
|
|
30
|
+
options,
|
|
31
|
+
notifyProgress,
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Note: Autocomplete provider setup moved here from CCC handler
|
|
38
|
+
// to preserve Pi-specific wiring in the adapter
|
|
39
|
+
}
|