@longtable/provider-claude 0.1.9 → 0.1.11
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/dist/index.d.ts +24 -0
- package/dist/index.js +69 -1
- package/dist/skills.d.ts +17 -0
- package/dist/skills.js +207 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
import type { ProviderCapabilities, QuestionRecord } from "@longtable/core";
|
|
1
2
|
import type { CheckpointSignal, ResearcherProfile, ResolvedCheckpointPolicy, RuntimeGuidance } from "@longtable/checkpoints";
|
|
2
3
|
import type { NumberedCheckpointSpec, SetupPersistedOutput } from "@longtable/setup";
|
|
3
4
|
export interface ClaudeChoice {
|
|
4
5
|
id: string;
|
|
5
6
|
label: string;
|
|
6
7
|
}
|
|
8
|
+
export interface ClaudeAskUserQuestionInput {
|
|
9
|
+
questions: Array<{
|
|
10
|
+
question: string;
|
|
11
|
+
header: string;
|
|
12
|
+
options: Array<{
|
|
13
|
+
label: string;
|
|
14
|
+
}>;
|
|
15
|
+
multiSelect: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
7
18
|
export interface ClaudeStructuredCheckpoint {
|
|
8
19
|
title: string;
|
|
9
20
|
instructions?: string;
|
|
@@ -24,8 +35,15 @@ export interface ClaudeCheckpointResult {
|
|
|
24
35
|
policy: ResolvedCheckpointPolicy;
|
|
25
36
|
guidance: RuntimeGuidance;
|
|
26
37
|
structuredPrompt: ClaudeStructuredCheckpoint;
|
|
38
|
+
askUserQuestionInput: ClaudeAskUserQuestionInput;
|
|
27
39
|
blocking: boolean;
|
|
28
40
|
}
|
|
41
|
+
export interface ClaudeRenderedQuestionRecord {
|
|
42
|
+
questionId: string;
|
|
43
|
+
checkpointKey: string;
|
|
44
|
+
structuredPrompt: ClaudeStructuredCheckpoint;
|
|
45
|
+
askUserQuestionInput: ClaudeAskUserQuestionInput;
|
|
46
|
+
}
|
|
29
47
|
export interface ClaudeRuntimeDefaults {
|
|
30
48
|
askAtLeastTwoQuestionsInExplore: boolean;
|
|
31
49
|
preserveNarrativeTraceInDraft: boolean;
|
|
@@ -40,7 +58,13 @@ export interface ClaudeRuntimeBridge {
|
|
|
40
58
|
profile: SetupPersistedOutput["profileSeed"];
|
|
41
59
|
runtimeDefaults: ClaudeRuntimeDefaults;
|
|
42
60
|
}
|
|
61
|
+
export declare const CLAUDE_PROVIDER_CAPABILITIES: ProviderCapabilities;
|
|
62
|
+
export declare function getClaudeProviderCapabilities(): ProviderCapabilities;
|
|
43
63
|
export declare function renderStructuredCheckpoint(spec: NumberedCheckpointSpec, guidance?: RuntimeGuidance): ClaudeStructuredCheckpoint;
|
|
64
|
+
export declare function renderAskUserQuestionInput(checkpoint: ClaudeStructuredCheckpoint): ClaudeAskUserQuestionInput;
|
|
65
|
+
export declare function renderStructuredQuestionRecord(record: QuestionRecord): ClaudeStructuredCheckpoint;
|
|
66
|
+
export declare function renderQuestionRecordInput(record: QuestionRecord): ClaudeRenderedQuestionRecord;
|
|
44
67
|
export declare function createClaudeCheckpoint(context: ClaudeCheckpointContext): ClaudeCheckpointResult;
|
|
45
68
|
export declare function createClaudeRuntimeBridge(setup: SetupPersistedOutput): ClaudeRuntimeBridge;
|
|
46
69
|
export * from "./config.js";
|
|
70
|
+
export * from "./skills.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { resolveCheckpointPolicy } from "@longtable/checkpoints";
|
|
2
2
|
import { resolveRuntimeGuidance } from "@longtable/checkpoints";
|
|
3
|
+
export const CLAUDE_PROVIDER_CAPABILITIES = {
|
|
4
|
+
provider: "claude",
|
|
5
|
+
nativeStructuredQuestions: true,
|
|
6
|
+
generatedSkills: "stable",
|
|
7
|
+
promptAliases: "unavailable",
|
|
8
|
+
nativeParallelSubagents: "session_dependent",
|
|
9
|
+
sequentialFallback: true,
|
|
10
|
+
mcpTransport: "planned",
|
|
11
|
+
notes: [
|
|
12
|
+
"Claude should prefer native structured questions when the runtime exposes them.",
|
|
13
|
+
"Generated LongTable skills are adapter output from the shared role registry.",
|
|
14
|
+
"Sequential panel fallback remains required so Claude and Codex share one semantic contract."
|
|
15
|
+
]
|
|
16
|
+
};
|
|
17
|
+
export function getClaudeProviderCapabilities() {
|
|
18
|
+
return CLAUDE_PROVIDER_CAPABILITIES;
|
|
19
|
+
}
|
|
3
20
|
function buildRequiredSections(guidance) {
|
|
4
21
|
const sections = [];
|
|
5
22
|
if (guidance.preferQuestionsFirst || guidance.minimumQuestions > 0) {
|
|
@@ -41,13 +58,63 @@ export function renderStructuredCheckpoint(spec, guidance) {
|
|
|
41
58
|
: undefined
|
|
42
59
|
};
|
|
43
60
|
}
|
|
61
|
+
export function renderAskUserQuestionInput(checkpoint) {
|
|
62
|
+
return {
|
|
63
|
+
questions: [
|
|
64
|
+
{
|
|
65
|
+
header: checkpoint.title,
|
|
66
|
+
question: checkpoint.instructions || checkpoint.title,
|
|
67
|
+
options: checkpoint.choices.map((choice) => ({
|
|
68
|
+
label: choice.label
|
|
69
|
+
})),
|
|
70
|
+
multiSelect: false
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function renderStructuredQuestionRecord(record) {
|
|
76
|
+
const choices = [
|
|
77
|
+
...record.prompt.options.map((option) => ({
|
|
78
|
+
id: option.value,
|
|
79
|
+
label: option.description ? `${option.label} — ${option.description}` : option.label
|
|
80
|
+
})),
|
|
81
|
+
...(record.prompt.allowOther
|
|
82
|
+
? [{
|
|
83
|
+
id: "other",
|
|
84
|
+
label: record.prompt.otherLabel ?? "Other"
|
|
85
|
+
}]
|
|
86
|
+
: [])
|
|
87
|
+
];
|
|
88
|
+
return {
|
|
89
|
+
title: record.prompt.title,
|
|
90
|
+
instructions: [
|
|
91
|
+
record.prompt.question,
|
|
92
|
+
...record.prompt.rationale.map((entry) => `Why now: ${entry}`),
|
|
93
|
+
`Question id: ${record.id}`,
|
|
94
|
+
`Checkpoint: ${record.prompt.checkpointKey ?? "manual"}`,
|
|
95
|
+
`Required: ${record.prompt.required ? "yes" : "no"}`
|
|
96
|
+
].join(" "),
|
|
97
|
+
choices
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function renderQuestionRecordInput(record) {
|
|
101
|
+
const structuredPrompt = renderStructuredQuestionRecord(record);
|
|
102
|
+
return {
|
|
103
|
+
questionId: record.id,
|
|
104
|
+
checkpointKey: record.prompt.checkpointKey ?? "manual",
|
|
105
|
+
structuredPrompt,
|
|
106
|
+
askUserQuestionInput: renderAskUserQuestionInput(structuredPrompt)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
44
109
|
export function createClaudeCheckpoint(context) {
|
|
45
110
|
const policy = resolveCheckpointPolicy(context.profile, context.signal);
|
|
46
111
|
const guidance = resolveRuntimeGuidance(context.profile, context.signal, policy);
|
|
112
|
+
const structuredPrompt = renderStructuredCheckpoint(context.spec, guidance);
|
|
47
113
|
return {
|
|
48
114
|
policy,
|
|
49
115
|
guidance,
|
|
50
|
-
structuredPrompt
|
|
116
|
+
structuredPrompt,
|
|
117
|
+
askUserQuestionInput: renderAskUserQuestionInput(structuredPrompt),
|
|
51
118
|
blocking: policy.blocking
|
|
52
119
|
};
|
|
53
120
|
}
|
|
@@ -67,3 +134,4 @@ export function createClaudeRuntimeBridge(setup) {
|
|
|
67
134
|
};
|
|
68
135
|
}
|
|
69
136
|
export * from "./config.js";
|
|
137
|
+
export * from "./skills.js";
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RoleDefinition } from "@longtable/core";
|
|
2
|
+
export interface ClaudeSkillSpec {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
triggers: string[];
|
|
6
|
+
body: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface InstalledClaudeSkill {
|
|
9
|
+
name: string;
|
|
10
|
+
path: string;
|
|
11
|
+
description: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function resolveClaudeSkillsDir(customDir?: string): string;
|
|
14
|
+
export declare function buildClaudeSkillSpecs(roles: RoleDefinition[]): ClaudeSkillSpec[];
|
|
15
|
+
export declare function installClaudeSkills(roles: RoleDefinition[], customDir?: string): Promise<InstalledClaudeSkill[]>;
|
|
16
|
+
export declare function removeClaudeSkills(roles: RoleDefinition[], customDir?: string): Promise<string[]>;
|
|
17
|
+
export declare function listInstalledClaudeSkills(roles: RoleDefinition[], customDir?: string): Promise<InstalledClaudeSkill[]>;
|
package/dist/skills.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
export function resolveClaudeSkillsDir(customDir) {
|
|
6
|
+
return customDir ? resolve(customDir) : join(homedir(), ".claude", "skills");
|
|
7
|
+
}
|
|
8
|
+
function skillNameForRole(role) {
|
|
9
|
+
return `longtable-${role.key.replaceAll("_", "-")}`;
|
|
10
|
+
}
|
|
11
|
+
function yamlString(value) {
|
|
12
|
+
return JSON.stringify(value);
|
|
13
|
+
}
|
|
14
|
+
function renderSkillFile(spec) {
|
|
15
|
+
return [
|
|
16
|
+
"---",
|
|
17
|
+
`name: ${spec.name}`,
|
|
18
|
+
`description: ${yamlString(spec.description)}`,
|
|
19
|
+
"triggers:",
|
|
20
|
+
...spec.triggers.map((trigger) => ` - ${yamlString(trigger)}`),
|
|
21
|
+
"---",
|
|
22
|
+
"",
|
|
23
|
+
`# ${spec.name}`,
|
|
24
|
+
"",
|
|
25
|
+
...spec.body
|
|
26
|
+
].join("\n");
|
|
27
|
+
}
|
|
28
|
+
function baseSkillSpecs() {
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
name: "longtable",
|
|
32
|
+
description: "Use for LongTable research conversations, project memory, checkpointing, and role routing.",
|
|
33
|
+
triggers: ["longtable", "lt ", "research workspace", "research checkpoint"],
|
|
34
|
+
body: [
|
|
35
|
+
"## Purpose",
|
|
36
|
+
"",
|
|
37
|
+
"Act as the LongTable adapter inside Claude Code. LongTable is a researcher-centered workspace, not a replacement for the researcher.",
|
|
38
|
+
"",
|
|
39
|
+
"## Invocation",
|
|
40
|
+
"",
|
|
41
|
+
"Use this skill when the user says things like:",
|
|
42
|
+
"",
|
|
43
|
+
"- `longtable: help me narrow this project`",
|
|
44
|
+
"- `lt explore: ...`",
|
|
45
|
+
"- `lt review: ...`",
|
|
46
|
+
"- `lt panel: ...`",
|
|
47
|
+
"",
|
|
48
|
+
"## Rules",
|
|
49
|
+
"",
|
|
50
|
+
"- Treat `.longtable/` state as the project source of truth when present.",
|
|
51
|
+
"- Prefer natural language over asking the researcher to run shell role commands.",
|
|
52
|
+
"- If a Researcher Checkpoint is needed, ask a short structured question with meaningful options and wait for the researcher.",
|
|
53
|
+
"- If changing LongTable product language, README positioning, or checkpoint policy, ask a Meta-Decision Checkpoint first.",
|
|
54
|
+
"- If a checkpoint allows `other`, make `other` visible instead of hiding it in state.",
|
|
55
|
+
"- Treat Claude's structured question surface as transport; LongTable state records are the source of truth.",
|
|
56
|
+
"- When the `longtable` CLI is available in a workspace, use `longtable question --print --provider claude --prompt \"...\"` to create a canonical checkpoint payload before invoking Claude's structured question surface.",
|
|
57
|
+
"- If `CURRENT.md` shows a pending required checkpoint, do not proceed until `longtable decide --question <id> --answer <value>` records the researcher's choice.",
|
|
58
|
+
"- Preserve open tensions and authorship instead of forcing closure.",
|
|
59
|
+
"- Disclose consulted roles with `LongTable consulted: ...` when a role is foregrounded.",
|
|
60
|
+
"- Label unsupported external claims as inference or estimate.",
|
|
61
|
+
"",
|
|
62
|
+
"## Optional CLI Bridge",
|
|
63
|
+
"",
|
|
64
|
+
"If the `longtable` command is available and canonical prompt rendering would help, use `longtable ask --print --prompt \"...\"` or `longtable panel --print --prompt \"...\"` as an adapter aid. Do not make shell commands the user's primary interface."
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "longtable-panel",
|
|
69
|
+
description: "Use when a research decision needs visible disagreement from multiple LongTable roles.",
|
|
70
|
+
triggers: ["lt panel", "longtable panel", "panel review", "team review", "disagreement", "conflict"],
|
|
71
|
+
body: [
|
|
72
|
+
"## Purpose",
|
|
73
|
+
"",
|
|
74
|
+
"Run a LongTable panel-style review in Claude Code.",
|
|
75
|
+
"",
|
|
76
|
+
"## Output Contract",
|
|
77
|
+
"",
|
|
78
|
+
"Return:",
|
|
79
|
+
"",
|
|
80
|
+
"1. LongTable synthesis",
|
|
81
|
+
"2. Panel opinions by role",
|
|
82
|
+
"3. Conflict summary",
|
|
83
|
+
"4. Decision prompt for the researcher",
|
|
84
|
+
"5. Evidence or file references used",
|
|
85
|
+
"",
|
|
86
|
+
"## Rules",
|
|
87
|
+
"",
|
|
88
|
+
"- Use multiple research perspectives when the request touches methods, theory, measurement, venue fit, ethics, or authorship.",
|
|
89
|
+
"- Do not collapse disagreement too early.",
|
|
90
|
+
"- Use a Researcher Checkpoint before treating panel synthesis as settled.",
|
|
91
|
+
"- If the CLI is available, prefer `longtable question --print --provider claude --prompt \"...\"` before invoking a structured question surface.",
|
|
92
|
+
"- Do not expose hidden reasoning or tool logs.",
|
|
93
|
+
"- If `.longtable/` exists, align the panel with `CURRENT.md` and project state.",
|
|
94
|
+
"- If `longtable panel --print --prompt \"...\"` is available, it may be used to obtain the canonical fallback prompt."
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "longtable-explore",
|
|
99
|
+
description: "Use for early-stage research exploration before the question is settled.",
|
|
100
|
+
triggers: ["lt explore", "explore research", "narrow research question", "problem framing"],
|
|
101
|
+
body: [
|
|
102
|
+
"## Purpose",
|
|
103
|
+
"",
|
|
104
|
+
"Help the researcher keep the problem open long enough to find a defensible question.",
|
|
105
|
+
"",
|
|
106
|
+
"## Rules",
|
|
107
|
+
"",
|
|
108
|
+
"- Ask at least two clarifying or tension questions before recommending a direction.",
|
|
109
|
+
"- Surface candidate boundaries, not just answers.",
|
|
110
|
+
"- Keep unresolved tensions visible.",
|
|
111
|
+
"- Avoid generic literature-search advice unless evidence discovery is actually requested."
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "longtable-review",
|
|
116
|
+
description: "Use for critical review of a claim, paragraph, study design, or plan.",
|
|
117
|
+
triggers: ["lt review", "review this", "criticize this", "what is weak"],
|
|
118
|
+
body: [
|
|
119
|
+
"## Purpose",
|
|
120
|
+
"",
|
|
121
|
+
"Review a research object without smoothing over its weaknesses.",
|
|
122
|
+
"",
|
|
123
|
+
"## Rules",
|
|
124
|
+
"",
|
|
125
|
+
"- Start with the most important risk or objection.",
|
|
126
|
+
"- Separate sourced facts, interpretation, and speculation.",
|
|
127
|
+
"- Preserve the researcher's own language where possible.",
|
|
128
|
+
"- Ask a checkpoint question before treating a high-stakes decision as settled."
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
function roleSkillSpec(role) {
|
|
134
|
+
const label = role.label;
|
|
135
|
+
return {
|
|
136
|
+
name: skillNameForRole(role),
|
|
137
|
+
description: `Use the LongTable ${label} role: ${role.shortDescription}`,
|
|
138
|
+
triggers: [
|
|
139
|
+
...role.synonyms.slice(0, 8),
|
|
140
|
+
`longtable ${role.key.replaceAll("_", " ")}`,
|
|
141
|
+
`lt ${role.key.replaceAll("_", " ")}`
|
|
142
|
+
],
|
|
143
|
+
body: [
|
|
144
|
+
"## Purpose",
|
|
145
|
+
"",
|
|
146
|
+
`Foreground the LongTable ${label} role.`,
|
|
147
|
+
"",
|
|
148
|
+
"## Role Focus",
|
|
149
|
+
"",
|
|
150
|
+
role.shortDescription,
|
|
151
|
+
"",
|
|
152
|
+
"## Rules",
|
|
153
|
+
"",
|
|
154
|
+
`- Disclose: \`LongTable consulted: ${label}\`.`,
|
|
155
|
+
"- Keep the role grounded in the user's research object and project state.",
|
|
156
|
+
"- Do not invent a separate role definition; this skill is an adapter generated from the LongTable role registry.",
|
|
157
|
+
"- If evidence is needed, ask whether the researcher wants scholarly search or citation verification.",
|
|
158
|
+
"- If the role's judgment would change the project direction, ask a Researcher Checkpoint before closure."
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
export function buildClaudeSkillSpecs(roles) {
|
|
163
|
+
return [...baseSkillSpecs(), ...roles.map(roleSkillSpec)];
|
|
164
|
+
}
|
|
165
|
+
export async function installClaudeSkills(roles, customDir) {
|
|
166
|
+
const skillsDir = resolveClaudeSkillsDir(customDir);
|
|
167
|
+
await mkdir(skillsDir, { recursive: true });
|
|
168
|
+
const installed = [];
|
|
169
|
+
for (const spec of buildClaudeSkillSpecs(roles)) {
|
|
170
|
+
const skillDir = join(skillsDir, spec.name);
|
|
171
|
+
await mkdir(skillDir, { recursive: true });
|
|
172
|
+
const path = join(skillDir, "SKILL.md");
|
|
173
|
+
await writeFile(path, renderSkillFile(spec), "utf8");
|
|
174
|
+
installed.push({
|
|
175
|
+
name: spec.name,
|
|
176
|
+
path,
|
|
177
|
+
description: spec.description
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return installed;
|
|
181
|
+
}
|
|
182
|
+
export async function removeClaudeSkills(roles, customDir) {
|
|
183
|
+
const skillsDir = resolveClaudeSkillsDir(customDir);
|
|
184
|
+
const removed = [];
|
|
185
|
+
for (const spec of buildClaudeSkillSpecs(roles)) {
|
|
186
|
+
const skillDir = join(skillsDir, spec.name);
|
|
187
|
+
if (existsSync(skillDir)) {
|
|
188
|
+
await rm(skillDir, { recursive: true, force: true });
|
|
189
|
+
removed.push(skillDir);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return removed;
|
|
193
|
+
}
|
|
194
|
+
export async function listInstalledClaudeSkills(roles, customDir) {
|
|
195
|
+
const skillsDir = resolveClaudeSkillsDir(customDir);
|
|
196
|
+
if (!existsSync(skillsDir)) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
const entries = new Set(await readdir(skillsDir));
|
|
200
|
+
return buildClaudeSkillSpecs(roles)
|
|
201
|
+
.filter((spec) => entries.has(spec.name) && existsSync(join(skillsDir, spec.name, "SKILL.md")))
|
|
202
|
+
.map((spec) => ({
|
|
203
|
+
name: spec.name,
|
|
204
|
+
path: join(skillsDir, spec.name, "SKILL.md"),
|
|
205
|
+
description: spec.description
|
|
206
|
+
}));
|
|
207
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longtable/provider-claude",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Claude adapter surface for LongTable",
|
|
6
6
|
"type": "module",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@longtable/checkpoints": "0.1.
|
|
25
|
-
"@longtable/core": "0.1.
|
|
26
|
-
"@longtable/setup": "0.1.
|
|
24
|
+
"@longtable/checkpoints": "0.1.11",
|
|
25
|
+
"@longtable/core": "0.1.11",
|
|
26
|
+
"@longtable/setup": "0.1.11"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"typescript": "^5.6.0"
|