@longtable/cli 0.1.4 → 0.1.5
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/README.md +1 -0
- package/dist/cli.js +35 -18
- package/dist/project-session.js +50 -9
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,24 @@ const VALID_STAGES = new Set([
|
|
|
27
27
|
"writing",
|
|
28
28
|
"submission"
|
|
29
29
|
]);
|
|
30
|
+
const ANSI = {
|
|
31
|
+
reset: "\u001B[0m",
|
|
32
|
+
bold: "\u001B[1m",
|
|
33
|
+
dim: "\u001B[2m",
|
|
34
|
+
cyan: "\u001B[36m",
|
|
35
|
+
green: "\u001B[32m"
|
|
36
|
+
};
|
|
37
|
+
function style(text, prefix) {
|
|
38
|
+
return `${prefix}${text}${ANSI.reset}`;
|
|
39
|
+
}
|
|
40
|
+
function renderSectionCard(title, body) {
|
|
41
|
+
return [
|
|
42
|
+
"┌──────────────────────────────────────────────┐",
|
|
43
|
+
`│ ${title.padEnd(44, " ")}│`,
|
|
44
|
+
"└──────────────────────────────────────────────┘",
|
|
45
|
+
...body
|
|
46
|
+
].join("\n");
|
|
47
|
+
}
|
|
30
48
|
function usage() {
|
|
31
49
|
return [
|
|
32
50
|
"Usage:",
|
|
@@ -122,15 +140,10 @@ function renderSetupHeader(flow) {
|
|
|
122
140
|
const subtitle = flow === "interview"
|
|
123
141
|
? "We will ask about your research persona, challenge preferences, and authorship defaults."
|
|
124
142
|
: "We will capture the minimum profile needed to start using Long Table.";
|
|
125
|
-
return [
|
|
126
|
-
"┌──────────────────────────────────────────────┐",
|
|
127
|
-
`│ ${title.padEnd(44, " ")}│`,
|
|
128
|
-
"└──────────────────────────────────────────────┘",
|
|
129
|
-
subtitle
|
|
130
|
-
].join("\n");
|
|
143
|
+
return renderSectionCard(title, [subtitle]);
|
|
131
144
|
}
|
|
132
145
|
function renderQuestionHeader(index, total, section, prompt) {
|
|
133
|
-
return [``, `[${index}/${total}] ${section}`, prompt].join("\n");
|
|
146
|
+
return [``, style(`[${index}/${total}] ${section}`, `${ANSI.bold}${ANSI.cyan}`), prompt].join("\n");
|
|
134
147
|
}
|
|
135
148
|
function questionSection(questionId) {
|
|
136
149
|
if (questionId === "field" || questionId === "careerStage" || questionId === "experienceLevel") {
|
|
@@ -154,9 +167,9 @@ function clearLine() {
|
|
|
154
167
|
return "\u001B[2K\r";
|
|
155
168
|
}
|
|
156
169
|
function renderArrowMenu(prompt, choices, selectedIndex) {
|
|
157
|
-
const lines = [prompt, "Use ↑/↓ and Enter."];
|
|
170
|
+
const lines = [style(prompt, ANSI.bold), style("Use ↑/↓ and Enter.", ANSI.dim)];
|
|
158
171
|
for (let index = 0; index < choices.length; index += 1) {
|
|
159
|
-
const prefix = index === selectedIndex ? ">" : " ";
|
|
172
|
+
const prefix = index === selectedIndex ? style(">", `${ANSI.bold}${ANSI.green}`) : " ";
|
|
160
173
|
lines.push(`${prefix} ${choices[index].label} - ${choices[index].description}`);
|
|
161
174
|
}
|
|
162
175
|
return lines.join("\n");
|
|
@@ -450,10 +463,10 @@ async function collectProjectInterview(setup, args) {
|
|
|
450
463
|
try {
|
|
451
464
|
if (needsInteractivePrompts) {
|
|
452
465
|
console.log("");
|
|
453
|
-
console.log("
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
466
|
+
console.log(renderSectionCard("Long Table Project Start", [
|
|
467
|
+
"We will create a project workspace and a session memory seed for today's work.",
|
|
468
|
+
"At the end, Long Table will tell you exactly which directory to open in Codex."
|
|
469
|
+
]));
|
|
457
470
|
console.log("");
|
|
458
471
|
}
|
|
459
472
|
const projectName = (typeof args.name === "string" && args.name.trim()) ||
|
|
@@ -855,11 +868,15 @@ async function runStart(args) {
|
|
|
855
868
|
}
|
|
856
869
|
console.log(renderProjectWorkspaceSummary(context));
|
|
857
870
|
console.log("");
|
|
858
|
-
console.log("Next
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
871
|
+
console.log(renderSectionCard("Next Step", [
|
|
872
|
+
`1. cd "${context.project.projectPath}"`,
|
|
873
|
+
"2. run `codex` in that directory",
|
|
874
|
+
"3. begin with your current goal in natural language",
|
|
875
|
+
"",
|
|
876
|
+
`Suggested first message: ${context.session.currentBlocker ? `"I want to work on ${context.session.currentGoal}. My current blocker is ${context.session.currentBlocker}."` : `"I want to work on ${context.session.currentGoal}."`}`,
|
|
877
|
+
"",
|
|
878
|
+
`Optional CLI path: longtable ask --cwd "${context.project.projectPath}" --prompt "${context.session.currentGoal.replaceAll("\"", "\\\"")}"`
|
|
879
|
+
]));
|
|
863
880
|
}
|
|
864
881
|
async function runCodexSubcommand(subcommand, args) {
|
|
865
882
|
const customDir = typeof args.dir === "string" ? args.dir : undefined;
|
package/dist/project-session.js
CHANGED
|
@@ -42,6 +42,37 @@ function buildWorkspaceGuide(project, session) {
|
|
|
42
42
|
];
|
|
43
43
|
return lines.join("\n");
|
|
44
44
|
}
|
|
45
|
+
function buildStartHereGuide(project, session) {
|
|
46
|
+
const lines = [
|
|
47
|
+
"# Start Here",
|
|
48
|
+
"",
|
|
49
|
+
`Project: ${project.projectName}`,
|
|
50
|
+
"",
|
|
51
|
+
"This workspace was created by Long Table for a single research project.",
|
|
52
|
+
"",
|
|
53
|
+
"## What to do now",
|
|
54
|
+
"1. Open Codex in this directory.",
|
|
55
|
+
"2. Start with your current goal, not a shell command.",
|
|
56
|
+
"3. Let Long Table keep disagreement visible when it matters.",
|
|
57
|
+
"",
|
|
58
|
+
"## Suggested first message",
|
|
59
|
+
session.currentBlocker
|
|
60
|
+
? `"I want to work on ${session.currentGoal}. My current blocker is: ${session.currentBlocker}."`
|
|
61
|
+
: `"I want to work on ${session.currentGoal}."`,
|
|
62
|
+
"",
|
|
63
|
+
"## What Long Table already knows in this directory",
|
|
64
|
+
`- Current goal: ${session.currentGoal}`,
|
|
65
|
+
...(session.currentBlocker ? [`- Current blocker: ${session.currentBlocker}`] : []),
|
|
66
|
+
`- Requested perspectives: ${session.requestedPerspectives.length > 0 ? session.requestedPerspectives.join(", ") : "auto"}`,
|
|
67
|
+
`- Disagreement visibility: ${session.disagreementPreference}`,
|
|
68
|
+
"",
|
|
69
|
+
"## Files",
|
|
70
|
+
"- `AGENTS.md` tells Codex how to behave in this workspace.",
|
|
71
|
+
"- `.longtable/current-session.json` stores the current session goal and blocker.",
|
|
72
|
+
"- `.longtable/project.json` stores the project-level record."
|
|
73
|
+
];
|
|
74
|
+
return lines.join("\n");
|
|
75
|
+
}
|
|
45
76
|
function buildProjectAgentsMd(project, session) {
|
|
46
77
|
return [
|
|
47
78
|
"# AGENTS.md",
|
|
@@ -60,6 +91,9 @@ function buildProjectAgentsMd(project, session) {
|
|
|
60
91
|
"- Begin exploratory work with clarifying or tension questions before recommending a direction.",
|
|
61
92
|
"- If you foreground role perspectives, disclose them with `Long Table consulted: ...`.",
|
|
62
93
|
"- Keep one accountable synthesis, but do not hide meaningful disagreement.",
|
|
94
|
+
...(session.disagreementPreference === "always_visible"
|
|
95
|
+
? ["- In this workspace, panel disagreement should be visible by default rather than hidden behind a single synthesis."]
|
|
96
|
+
: []),
|
|
63
97
|
"- Do not expose internal tool logs, file-search traces, or process commentary in the researcher-facing answer.",
|
|
64
98
|
"",
|
|
65
99
|
"## Session memory",
|
|
@@ -161,6 +195,7 @@ export async function createOrUpdateProjectWorkspace(options) {
|
|
|
161
195
|
await writeFile(join(sessionsDir, `${sessionId}.json`), JSON.stringify(session, null, 2), "utf8");
|
|
162
196
|
await writeFile(join(metaDir, "state.json"), buildStateSeed(project, session, options.setup), "utf8");
|
|
163
197
|
await writeFile(join(projectPath, "LONGTABLE.md"), buildWorkspaceGuide(project, session), "utf8");
|
|
198
|
+
await writeFile(join(projectPath, "START-HERE.md"), buildStartHereGuide(project, session), "utf8");
|
|
164
199
|
await writeFile(join(projectPath, "AGENTS.md"), buildProjectAgentsMd(project, session), "utf8");
|
|
165
200
|
return {
|
|
166
201
|
project,
|
|
@@ -194,14 +229,20 @@ export async function loadProjectContextFromDirectory(startPath) {
|
|
|
194
229
|
}
|
|
195
230
|
export function renderProjectWorkspaceSummary(context) {
|
|
196
231
|
return [
|
|
197
|
-
"
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
`
|
|
201
|
-
|
|
202
|
-
`
|
|
203
|
-
`
|
|
204
|
-
`
|
|
205
|
-
`
|
|
232
|
+
"┌──────────────────────────────────────────────┐",
|
|
233
|
+
"│ Long Table Project Workspace │",
|
|
234
|
+
"└──────────────────────────────────────────────┘",
|
|
235
|
+
`Project: ${context.project.projectName}`,
|
|
236
|
+
`Path: ${context.project.projectPath}`,
|
|
237
|
+
`Goal: ${context.session.currentGoal}`,
|
|
238
|
+
...(context.session.currentBlocker ? [`Blocker: ${context.session.currentBlocker}`] : []),
|
|
239
|
+
`Perspectives: ${context.session.requestedPerspectives.length > 0 ? context.session.requestedPerspectives.join(", ") : "auto"}`,
|
|
240
|
+
`Disagreement: ${context.session.disagreementPreference}`,
|
|
241
|
+
"",
|
|
242
|
+
"Created files:",
|
|
243
|
+
`- ${context.projectFilePath}`,
|
|
244
|
+
`- ${context.sessionFilePath}`,
|
|
245
|
+
`- ${join(context.project.projectPath, "START-HERE.md")}`,
|
|
246
|
+
`- ${join(context.project.projectPath, "AGENTS.md")}`
|
|
206
247
|
].join("\n");
|
|
207
248
|
}
|