intent-log 0.1.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/README.md +64 -0
- package/dist/adapter/__tests__/claude-code-log-reader.test.d.ts +1 -0
- package/dist/adapter/__tests__/claude-code-log-reader.test.js +197 -0
- package/dist/adapter/__tests__/claude-code-log-reader.test.js.map +1 -0
- package/dist/adapter/__tests__/filesystem-repository.test.d.ts +1 -0
- package/dist/adapter/__tests__/filesystem-repository.test.js +152 -0
- package/dist/adapter/__tests__/filesystem-repository.test.js.map +1 -0
- package/dist/adapter/__tests__/privacy-filter.test.d.ts +1 -0
- package/dist/adapter/__tests__/privacy-filter.test.js +61 -0
- package/dist/adapter/__tests__/privacy-filter.test.js.map +1 -0
- package/dist/adapter/claude-code-log-reader.d.ts +11 -0
- package/dist/adapter/claude-code-log-reader.js +133 -0
- package/dist/adapter/claude-code-log-reader.js.map +1 -0
- package/dist/adapter/claude-code-summarizer.d.ts +6 -0
- package/dist/adapter/claude-code-summarizer.js +93 -0
- package/dist/adapter/claude-code-summarizer.js.map +1 -0
- package/dist/adapter/filesystem-repository.d.ts +39 -0
- package/dist/adapter/filesystem-repository.js +98 -0
- package/dist/adapter/filesystem-repository.js.map +1 -0
- package/dist/adapter/privacy-filter.d.ts +8 -0
- package/dist/adapter/privacy-filter.js +58 -0
- package/dist/adapter/privacy-filter.js.map +1 -0
- package/dist/cli/collect.d.ts +1 -0
- package/dist/cli/collect.js +19 -0
- package/dist/cli/collect.js.map +1 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +39 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/log.d.ts +1 -0
- package/dist/cli/log.js +15 -0
- package/dist/cli/log.js.map +1 -0
- package/dist/cli/reset.d.ts +1 -0
- package/dist/cli/reset.js +7 -0
- package/dist/cli/reset.js.map +1 -0
- package/dist/cli/rm.d.ts +1 -0
- package/dist/cli/rm.js +7 -0
- package/dist/cli/rm.js.map +1 -0
- package/dist/cli/show.d.ts +1 -0
- package/dist/cli/show.js +21 -0
- package/dist/cli/show.js.map +1 -0
- package/dist/domain/__tests__/session.test.d.ts +1 -0
- package/dist/domain/__tests__/session.test.js +80 -0
- package/dist/domain/__tests__/session.test.js.map +1 -0
- package/dist/domain/__tests__/step.test.d.ts +1 -0
- package/dist/domain/__tests__/step.test.js +65 -0
- package/dist/domain/__tests__/step.test.js.map +1 -0
- package/dist/domain/session.d.ts +51 -0
- package/dist/domain/session.js +49 -0
- package/dist/domain/session.js.map +1 -0
- package/dist/domain/step.d.ts +13 -0
- package/dist/domain/step.js +98 -0
- package/dist/domain/step.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/port/agent-log-reader.d.ts +6 -0
- package/dist/port/agent-log-reader.js +2 -0
- package/dist/port/agent-log-reader.js.map +1 -0
- package/dist/port/step-repository.d.ts +7 -0
- package/dist/port/step-repository.js +2 -0
- package/dist/port/step-repository.js.map +1 -0
- package/dist/port/summarizer.d.ts +13 -0
- package/dist/port/summarizer.js +2 -0
- package/dist/port/summarizer.js.map +1 -0
- package/dist/usecase/__tests__/collect.test.d.ts +1 -0
- package/dist/usecase/__tests__/collect.test.js +135 -0
- package/dist/usecase/__tests__/collect.test.js.map +1 -0
- package/dist/usecase/collect.d.ts +16 -0
- package/dist/usecase/collect.js +190 -0
- package/dist/usecase/collect.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { toMarkdown, fromMarkdown } from "../step.js";
|
|
3
|
+
const baseStep = {
|
|
4
|
+
number: 1,
|
|
5
|
+
title: "テスト機能追加",
|
|
6
|
+
session: "abc-123",
|
|
7
|
+
timestamp: new Date("2025-01-15T10:30:00Z"),
|
|
8
|
+
tags: ["feature", "test"],
|
|
9
|
+
prompt: "テスト機能を追加してください",
|
|
10
|
+
reasoning: "品質向上のため",
|
|
11
|
+
outcome: "テストが追加された",
|
|
12
|
+
friction: "型エラーが発生した",
|
|
13
|
+
};
|
|
14
|
+
describe("toMarkdown", () => {
|
|
15
|
+
it("全フィールドを正常に出力する", () => {
|
|
16
|
+
const md = toMarkdown(baseStep);
|
|
17
|
+
expect(md).toContain("step: 1");
|
|
18
|
+
expect(md).toContain('title: "テスト機能追加"');
|
|
19
|
+
expect(md).toContain('session: "abc-123"');
|
|
20
|
+
expect(md).toContain("timestamp: 2025-01-15T10:30:00Z");
|
|
21
|
+
expect(md).toContain("tags: [feature, test]");
|
|
22
|
+
expect(md).toContain("## prompt\n\nテスト機能を追加してください");
|
|
23
|
+
expect(md).toContain("## reasoning\n\n品質向上のため");
|
|
24
|
+
expect(md).toContain("## outcome\n\nテストが追加された");
|
|
25
|
+
expect(md).toContain("## friction\n\n型エラーが発生した");
|
|
26
|
+
});
|
|
27
|
+
it("frictionが空なら省略する", () => {
|
|
28
|
+
const step = { ...baseStep, friction: "" };
|
|
29
|
+
const md = toMarkdown(step);
|
|
30
|
+
expect(md).not.toContain("## friction");
|
|
31
|
+
});
|
|
32
|
+
it("tagsが空なら[]を出力する", () => {
|
|
33
|
+
const step = { ...baseStep, tags: [] };
|
|
34
|
+
const md = toMarkdown(step);
|
|
35
|
+
expect(md).toContain("tags: []");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe("fromMarkdown", () => {
|
|
39
|
+
it("正常にパースできる", () => {
|
|
40
|
+
const md = toMarkdown(baseStep);
|
|
41
|
+
const parsed = fromMarkdown(md);
|
|
42
|
+
expect(parsed.number).toBe(1);
|
|
43
|
+
expect(parsed.title).toBe("テスト機能追加");
|
|
44
|
+
expect(parsed.session).toBe("abc-123");
|
|
45
|
+
expect(parsed.timestamp.toISOString()).toBe("2025-01-15T10:30:00.000Z");
|
|
46
|
+
expect(parsed.tags).toEqual(["feature", "test"]);
|
|
47
|
+
expect(parsed.prompt).toBe("テスト機能を追加してください");
|
|
48
|
+
expect(parsed.reasoning).toBe("品質向上のため");
|
|
49
|
+
expect(parsed.outcome).toBe("テストが追加された");
|
|
50
|
+
expect(parsed.friction).toBe("型エラーが発生した");
|
|
51
|
+
});
|
|
52
|
+
it("frontmatterがなければエラー", () => {
|
|
53
|
+
expect(() => fromMarkdown("no frontmatter")).toThrow("frontmatterが見つかりません");
|
|
54
|
+
});
|
|
55
|
+
it("frontmatter終了がなければエラー", () => {
|
|
56
|
+
expect(() => fromMarkdown("---\nstep: 1\n")).toThrow("frontmatterの終了が見つかりません");
|
|
57
|
+
});
|
|
58
|
+
it("toMarkdown → fromMarkdown のラウンドトリップ", () => {
|
|
59
|
+
const md = toMarkdown(baseStep);
|
|
60
|
+
const parsed = fromMarkdown(md);
|
|
61
|
+
const md2 = toMarkdown(parsed);
|
|
62
|
+
expect(md).toBe(md2);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=step.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.test.js","sourceRoot":"","sources":["../../../src/domain/__tests__/step.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
declare const ContentBlock: z.ZodUnion<readonly [z.ZodObject<{
|
|
3
|
+
type: z.ZodLiteral<"text">;
|
|
4
|
+
text: z.ZodString;
|
|
5
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
6
|
+
type: z.ZodLiteral<"thinking">;
|
|
7
|
+
thinking: z.ZodString;
|
|
8
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
9
|
+
type: z.ZodLiteral<"tool_use">;
|
|
10
|
+
name: z.ZodString;
|
|
11
|
+
input: z.ZodUnknown;
|
|
12
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
13
|
+
type: z.ZodLiteral<"tool_result">;
|
|
14
|
+
content: z.ZodOptional<z.ZodUnknown>;
|
|
15
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
16
|
+
type: z.ZodString;
|
|
17
|
+
}, z.core.$strip>]>;
|
|
18
|
+
export declare const SessionEntry: z.ZodObject<{
|
|
19
|
+
type: z.ZodString;
|
|
20
|
+
isSidechain: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
message: z.ZodOptional<z.ZodObject<{
|
|
22
|
+
role: z.ZodString;
|
|
23
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
24
|
+
type: z.ZodLiteral<"text">;
|
|
25
|
+
text: z.ZodString;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
type: z.ZodLiteral<"thinking">;
|
|
28
|
+
thinking: z.ZodString;
|
|
29
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
30
|
+
type: z.ZodLiteral<"tool_use">;
|
|
31
|
+
name: z.ZodString;
|
|
32
|
+
input: z.ZodUnknown;
|
|
33
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
34
|
+
type: z.ZodLiteral<"tool_result">;
|
|
35
|
+
content: z.ZodOptional<z.ZodUnknown>;
|
|
36
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
37
|
+
type: z.ZodString;
|
|
38
|
+
}, z.core.$strip>]>>]>;
|
|
39
|
+
}, z.core.$strip>>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
export type SessionEntry = z.infer<typeof SessionEntry>;
|
|
42
|
+
export type ContentBlock = z.infer<typeof ContentBlock>;
|
|
43
|
+
export interface ConversationTurn {
|
|
44
|
+
userPrompt: string;
|
|
45
|
+
assistantThinking: string[];
|
|
46
|
+
assistantText: string[];
|
|
47
|
+
toolUses: string[];
|
|
48
|
+
skills: string[];
|
|
49
|
+
}
|
|
50
|
+
export declare function summaryContext(turn: ConversationTurn): string;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
const ContentBlockText = z.object({
|
|
3
|
+
type: z.literal("text"),
|
|
4
|
+
text: z.string(),
|
|
5
|
+
});
|
|
6
|
+
const ContentBlockThinking = z.object({
|
|
7
|
+
type: z.literal("thinking"),
|
|
8
|
+
thinking: z.string(),
|
|
9
|
+
});
|
|
10
|
+
const ContentBlockToolUse = z.object({
|
|
11
|
+
type: z.literal("tool_use"),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
input: z.unknown(),
|
|
14
|
+
});
|
|
15
|
+
const ContentBlockToolResult = z.object({
|
|
16
|
+
type: z.literal("tool_result"),
|
|
17
|
+
content: z.unknown().optional(),
|
|
18
|
+
});
|
|
19
|
+
const ContentBlock = z.union([
|
|
20
|
+
ContentBlockText,
|
|
21
|
+
ContentBlockThinking,
|
|
22
|
+
ContentBlockToolUse,
|
|
23
|
+
ContentBlockToolResult,
|
|
24
|
+
z.object({ type: z.string() }), // Other
|
|
25
|
+
]);
|
|
26
|
+
const MessageContent = z.union([z.string(), z.array(ContentBlock)]);
|
|
27
|
+
const Message = z.object({
|
|
28
|
+
role: z.string(),
|
|
29
|
+
content: MessageContent,
|
|
30
|
+
});
|
|
31
|
+
export const SessionEntry = z.object({
|
|
32
|
+
type: z.string(),
|
|
33
|
+
isSidechain: z.boolean().optional(),
|
|
34
|
+
message: Message.optional(),
|
|
35
|
+
});
|
|
36
|
+
export function summaryContext(turn) {
|
|
37
|
+
let ctx = `## ユーザーの指示\n${turn.userPrompt}\n`;
|
|
38
|
+
if (turn.assistantThinking.length > 0) {
|
|
39
|
+
ctx += `\n## AIの思考\n${turn.assistantThinking.join("\n")}\n`;
|
|
40
|
+
}
|
|
41
|
+
if (turn.assistantText.length > 0) {
|
|
42
|
+
ctx += `\n## AIの応答\n${turn.assistantText.join("\n")}\n`;
|
|
43
|
+
}
|
|
44
|
+
if (turn.toolUses.length > 0) {
|
|
45
|
+
ctx += `\n## 使用ツール\n${turn.toolUses.join(", ")}\n`;
|
|
46
|
+
}
|
|
47
|
+
return ctx;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/domain/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,gBAAgB;IAChB,oBAAoB;IACpB,mBAAmB;IACnB,sBAAsB;IACtB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ;CACzC,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,cAAc;CACxB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAaH,MAAM,UAAU,cAAc,CAAC,IAAsB;IACnD,IAAI,GAAG,GAAG,eAAe,IAAI,CAAC,UAAU,IAAI,CAAC;IAC7C,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,GAAG,IAAI,eAAe,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC9D,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,GAAG,IAAI,eAAe,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1D,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,GAAG,IAAI,eAAe,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Step {
|
|
2
|
+
number: number;
|
|
3
|
+
title: string;
|
|
4
|
+
session: string;
|
|
5
|
+
timestamp: Date;
|
|
6
|
+
tags: string[];
|
|
7
|
+
prompt: string;
|
|
8
|
+
reasoning: string;
|
|
9
|
+
outcome: string;
|
|
10
|
+
friction: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function toMarkdown(step: Step): string;
|
|
13
|
+
export declare function fromMarkdown(content: string): Step;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export function toMarkdown(step) {
|
|
2
|
+
const tagsStr = step.tags.length === 0 ? "[]" : `[${step.tags.join(", ")}]`;
|
|
3
|
+
const ts = step.timestamp.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
4
|
+
let md = `---
|
|
5
|
+
step: ${step.number}
|
|
6
|
+
title: "${step.title}"
|
|
7
|
+
session: "${step.session}"
|
|
8
|
+
timestamp: ${ts}
|
|
9
|
+
tags: ${tagsStr}
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## prompt
|
|
13
|
+
|
|
14
|
+
${step.prompt}
|
|
15
|
+
|
|
16
|
+
## reasoning
|
|
17
|
+
|
|
18
|
+
${step.reasoning}
|
|
19
|
+
|
|
20
|
+
## outcome
|
|
21
|
+
|
|
22
|
+
${step.outcome}`;
|
|
23
|
+
if (step.friction) {
|
|
24
|
+
md += `\n\n## friction\n\n${step.friction}`;
|
|
25
|
+
}
|
|
26
|
+
md += "\n";
|
|
27
|
+
return md;
|
|
28
|
+
}
|
|
29
|
+
export function fromMarkdown(content) {
|
|
30
|
+
const trimmed = content.trimStart();
|
|
31
|
+
if (!trimmed.startsWith("---")) {
|
|
32
|
+
throw new Error("frontmatterが見つかりません");
|
|
33
|
+
}
|
|
34
|
+
const rest = trimmed.slice(3);
|
|
35
|
+
const endIdx = rest.indexOf("---");
|
|
36
|
+
if (endIdx === -1) {
|
|
37
|
+
throw new Error("frontmatterの終了が見つかりません");
|
|
38
|
+
}
|
|
39
|
+
const frontmatter = rest.slice(0, endIdx).trim();
|
|
40
|
+
const body = rest.slice(endIdx + 3).trim();
|
|
41
|
+
const number = parseInt(extractField(frontmatter, "step"), 10);
|
|
42
|
+
if (isNaN(number))
|
|
43
|
+
throw new Error("step番号のパースに失敗");
|
|
44
|
+
const title = extractField(frontmatter, "title");
|
|
45
|
+
const session = extractField(frontmatter, "session");
|
|
46
|
+
const timestampStr = extractField(frontmatter, "timestamp");
|
|
47
|
+
const timestamp = new Date(timestampStr);
|
|
48
|
+
if (isNaN(timestamp.getTime())) {
|
|
49
|
+
throw new Error(`timestampのパースに失敗: ${timestampStr}`);
|
|
50
|
+
}
|
|
51
|
+
const tagsStr = extractFieldOptional(frontmatter, "tags") ?? "[]";
|
|
52
|
+
const tags = parseTags(tagsStr);
|
|
53
|
+
return {
|
|
54
|
+
number,
|
|
55
|
+
title,
|
|
56
|
+
session,
|
|
57
|
+
timestamp,
|
|
58
|
+
tags,
|
|
59
|
+
prompt: extractSection(body, "prompt"),
|
|
60
|
+
reasoning: extractSection(body, "reasoning"),
|
|
61
|
+
outcome: extractSection(body, "outcome"),
|
|
62
|
+
friction: extractSection(body, "friction"),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function extractField(frontmatter, key) {
|
|
66
|
+
for (const line of frontmatter.split("\n")) {
|
|
67
|
+
if (line.startsWith(`${key}:`)) {
|
|
68
|
+
const val = line.slice(key.length + 1).trim();
|
|
69
|
+
return val.replace(/^"|"$/g, "");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`フィールド '${key}' が見つかりません`);
|
|
73
|
+
}
|
|
74
|
+
function extractFieldOptional(frontmatter, key) {
|
|
75
|
+
try {
|
|
76
|
+
return extractField(frontmatter, key);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function parseTags(s) {
|
|
83
|
+
const inner = s.trim().replace(/^\[/, "").replace(/\]$/, "");
|
|
84
|
+
if (!inner)
|
|
85
|
+
return [];
|
|
86
|
+
return inner.split(",").map((t) => t.trim());
|
|
87
|
+
}
|
|
88
|
+
function extractSection(body, section) {
|
|
89
|
+
const header = `## ${section}`;
|
|
90
|
+
const start = body.indexOf(header);
|
|
91
|
+
if (start === -1)
|
|
92
|
+
return "";
|
|
93
|
+
const afterHeader = body.slice(start + header.length);
|
|
94
|
+
const end = afterHeader.indexOf("\n## ");
|
|
95
|
+
const content = end === -1 ? afterHeader : afterHeader.slice(0, end);
|
|
96
|
+
return content.trim();
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/domain/step.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { initCommand } from "./cli/init.js";
|
|
4
|
+
import { collectCommand } from "./cli/collect.js";
|
|
5
|
+
import { logCommand } from "./cli/log.js";
|
|
6
|
+
import { showCommand } from "./cli/show.js";
|
|
7
|
+
import { resetCommand } from "./cli/reset.js";
|
|
8
|
+
import { rmCommand } from "./cli/rm.js";
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name("intent")
|
|
12
|
+
.description("意図のバージョン管理CLI — AIとの対話ログから意図の進化過程を抽出・構造化")
|
|
13
|
+
.version("0.1.0");
|
|
14
|
+
program
|
|
15
|
+
.command("init")
|
|
16
|
+
.description(".intent/ を初期化")
|
|
17
|
+
.action(async () => {
|
|
18
|
+
try {
|
|
19
|
+
await initCommand();
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
program
|
|
27
|
+
.command("collect")
|
|
28
|
+
.description("ログから意図を収集")
|
|
29
|
+
.option("--session <id>", "特定セッションだけ収集")
|
|
30
|
+
.action(async (opts) => {
|
|
31
|
+
try {
|
|
32
|
+
await collectCommand(opts.session);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
program
|
|
40
|
+
.command("log")
|
|
41
|
+
.description("ステップ一覧を表示")
|
|
42
|
+
.action(async () => {
|
|
43
|
+
try {
|
|
44
|
+
await logCommand();
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
program
|
|
52
|
+
.command("show")
|
|
53
|
+
.description("特定ステップの詳細表示")
|
|
54
|
+
.argument("<step>", "ステップ番号")
|
|
55
|
+
.action(async (step) => {
|
|
56
|
+
try {
|
|
57
|
+
await showCommand(parseInt(step, 10));
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
program
|
|
65
|
+
.command("reset")
|
|
66
|
+
.description("すべてのステップとセッション履歴をリセット")
|
|
67
|
+
.option("--yes", "確認プロンプトをスキップ")
|
|
68
|
+
.action(async (opts) => {
|
|
69
|
+
try {
|
|
70
|
+
if (!opts.yes) {
|
|
71
|
+
const { createInterface } = await import("node:readline");
|
|
72
|
+
const rl = createInterface({
|
|
73
|
+
input: process.stdin,
|
|
74
|
+
output: process.stdout,
|
|
75
|
+
});
|
|
76
|
+
const answer = await new Promise((resolve) => {
|
|
77
|
+
rl.question("すべてのステップとセッション履歴を削除します。よろしいですか? (y/N) ", resolve);
|
|
78
|
+
});
|
|
79
|
+
rl.close();
|
|
80
|
+
if (answer.toLowerCase() !== "y") {
|
|
81
|
+
console.log("キャンセルしました。");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await resetCommand();
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
program
|
|
93
|
+
.command("rm")
|
|
94
|
+
.description("特定のステップを削除")
|
|
95
|
+
.argument("<step>", "ステップ番号")
|
|
96
|
+
.action(async (step) => {
|
|
97
|
+
try {
|
|
98
|
+
await rmCommand(parseInt(step, 10));
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
console.error(`エラー: ${e instanceof Error ? e.message : e}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
program.parse();
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-log-reader.js","sourceRoot":"","sources":["../../src/port/agent-log-reader.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-repository.js","sourceRoot":"","sources":["../../src/port/step-repository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConversationTurn } from "../domain/session.js";
|
|
2
|
+
import type { Step } from "../domain/step.js";
|
|
3
|
+
export interface StepDraft {
|
|
4
|
+
title: string;
|
|
5
|
+
prompt: string;
|
|
6
|
+
reasoning: string;
|
|
7
|
+
outcome: string;
|
|
8
|
+
tags?: string[];
|
|
9
|
+
skip?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface Summarizer {
|
|
12
|
+
summarize(turns: ConversationTurn[], previousSteps: Step[]): Promise<StepDraft | null>;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/port/summarizer.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parsePlanText, parseSkillSession } from "../collect.js";
|
|
3
|
+
function makeTurn(prompt, skills = [], toolUses = []) {
|
|
4
|
+
return {
|
|
5
|
+
userPrompt: prompt,
|
|
6
|
+
assistantThinking: [],
|
|
7
|
+
assistantText: [],
|
|
8
|
+
toolUses,
|
|
9
|
+
skills,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const planPrompt = `Implement the following plan:
|
|
13
|
+
|
|
14
|
+
# プラン実行セッションからの意図抽出
|
|
15
|
+
|
|
16
|
+
## Context
|
|
17
|
+
|
|
18
|
+
\`intent collect\` で claude-panes プロジェクトを収集すると、22セッション中 3つしか収集されない。調査の結果、17セッションが \`Implement the following plan:\` で始まるプラン実行セッションで、一律スキップされていた。
|
|
19
|
+
|
|
20
|
+
## 変更
|
|
21
|
+
|
|
22
|
+
### 1. \`src/usecase/collect.ts\` — プラン実行セッションの処理
|
|
23
|
+
|
|
24
|
+
parsePlanText() ヘルパーを追加。
|
|
25
|
+
|
|
26
|
+
### 2. \`src/adapter/claude-code-summarizer.ts\` — プロンプト修正
|
|
27
|
+
|
|
28
|
+
skip 指示を削除。
|
|
29
|
+
|
|
30
|
+
### 3. テスト追加
|
|
31
|
+
|
|
32
|
+
テストを新規作成。
|
|
33
|
+
|
|
34
|
+
## 検証
|
|
35
|
+
|
|
36
|
+
npm run build && npm test
|
|
37
|
+
`;
|
|
38
|
+
describe("parsePlanText", () => {
|
|
39
|
+
it("タイトルと Context を正しく抽出する", () => {
|
|
40
|
+
const draft = parsePlanText(planPrompt);
|
|
41
|
+
expect(draft).not.toBeNull();
|
|
42
|
+
expect(draft.title).toBe("プラン実行セッションからの意図抽出");
|
|
43
|
+
expect(draft.prompt).toContain("intent collect");
|
|
44
|
+
expect(draft.prompt).toContain("一律スキップされていた");
|
|
45
|
+
expect(draft.tags).toEqual(["plan"]);
|
|
46
|
+
expect(draft.outcome).toContain("実装完了");
|
|
47
|
+
});
|
|
48
|
+
it("変更セクションからファイル一覧を reasoning に含める", () => {
|
|
49
|
+
const draft = parsePlanText(planPrompt);
|
|
50
|
+
expect(draft).not.toBeNull();
|
|
51
|
+
expect(draft.reasoning).toContain("src/usecase/collect.ts");
|
|
52
|
+
expect(draft.reasoning).toContain("src/adapter/claude-code-summarizer.ts");
|
|
53
|
+
});
|
|
54
|
+
it("Context なしのプランで null を返す", () => {
|
|
55
|
+
const noContext = `Implement the following plan:
|
|
56
|
+
|
|
57
|
+
# タイトルだけのプラン
|
|
58
|
+
|
|
59
|
+
## 変更
|
|
60
|
+
|
|
61
|
+
何かの変更
|
|
62
|
+
`;
|
|
63
|
+
const draft = parsePlanText(noContext);
|
|
64
|
+
expect(draft).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
it("長いタイトルが30文字に切り詰められる", () => {
|
|
67
|
+
const longTitle = `Implement the following plan:
|
|
68
|
+
|
|
69
|
+
# これは非常に長いタイトルで30文字を超えるため切り詰めが必要になるはずです
|
|
70
|
+
|
|
71
|
+
## Context
|
|
72
|
+
|
|
73
|
+
何かのコンテキスト。
|
|
74
|
+
`;
|
|
75
|
+
const draft = parsePlanText(longTitle);
|
|
76
|
+
expect(draft).not.toBeNull();
|
|
77
|
+
expect(draft.title.length).toBeLessThanOrEqual(30);
|
|
78
|
+
});
|
|
79
|
+
it("プレフィックスのみで本文がない場合は null を返す", () => {
|
|
80
|
+
const draft = parsePlanText("Implement the following plan:");
|
|
81
|
+
expect(draft).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
it("タイトルがない場合は null を返す", () => {
|
|
84
|
+
const noTitle = `Implement the following plan:
|
|
85
|
+
|
|
86
|
+
## Context
|
|
87
|
+
|
|
88
|
+
何かのコンテキスト。
|
|
89
|
+
`;
|
|
90
|
+
const draft = parsePlanText(noTitle);
|
|
91
|
+
expect(draft).toBeNull();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe("parseSkillSession", () => {
|
|
95
|
+
it("Skill tool_use を含むセッションから StepDraft を生成する", () => {
|
|
96
|
+
const turns = [makeTurn("/commit", ["commit"], ["Skill"])];
|
|
97
|
+
const draft = parseSkillSession(turns);
|
|
98
|
+
expect(draft).not.toBeNull();
|
|
99
|
+
expect(draft.title).toBe("/commit スキル実行");
|
|
100
|
+
expect(draft.prompt).toBe("/commit");
|
|
101
|
+
expect(draft.tags).toEqual(["skill"]);
|
|
102
|
+
expect(draft.outcome).toContain("commit");
|
|
103
|
+
});
|
|
104
|
+
it("namespaced スキル名を正規化する", () => {
|
|
105
|
+
const turns = [
|
|
106
|
+
makeTurn("/commit", ["commit-commands:commit"], ["Skill"]),
|
|
107
|
+
];
|
|
108
|
+
const draft = parseSkillSession(turns);
|
|
109
|
+
expect(draft).not.toBeNull();
|
|
110
|
+
expect(draft.title).toBe("/commit スキル実行");
|
|
111
|
+
});
|
|
112
|
+
it("skills が空のセッションでは null を返す", () => {
|
|
113
|
+
const turns = [makeTurn("通常の質問", [], ["Read", "Edit"])];
|
|
114
|
+
const draft = parseSkillSession(turns);
|
|
115
|
+
expect(draft).toBeNull();
|
|
116
|
+
});
|
|
117
|
+
it("複数ターンにまたがるスキルを集約する", () => {
|
|
118
|
+
const turns = [
|
|
119
|
+
makeTurn("/review-pr", ["code-review:code-review"], ["Skill"]),
|
|
120
|
+
makeTurn("修正して", ["commit-commands:commit"], ["Skill"]),
|
|
121
|
+
];
|
|
122
|
+
const draft = parseSkillSession(turns);
|
|
123
|
+
expect(draft).not.toBeNull();
|
|
124
|
+
expect(draft.title).toBe("/code-review スキル実行");
|
|
125
|
+
expect(draft.reasoning).toContain("code-review");
|
|
126
|
+
expect(draft.reasoning).toContain("commit");
|
|
127
|
+
});
|
|
128
|
+
it("userPrompt が空でもスキル名をフォールバックに使う", () => {
|
|
129
|
+
const turns = [makeTurn("", ["commit"], ["Skill"])];
|
|
130
|
+
const draft = parseSkillSession(turns);
|
|
131
|
+
expect(draft).not.toBeNull();
|
|
132
|
+
expect(draft.prompt).toBe("/commit");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=collect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect.test.js","sourceRoot":"","sources":["../../../src/usecase/__tests__/collect.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentLogReader } from "../port/agent-log-reader.js";
|
|
2
|
+
import type { Summarizer, StepDraft } from "../port/summarizer.js";
|
|
3
|
+
import type { PrivacyFilter } from "../adapter/privacy-filter.js";
|
|
4
|
+
import type { FileSystemRepository } from "../adapter/filesystem-repository.js";
|
|
5
|
+
import type { ConversationTurn } from "../domain/session.js";
|
|
6
|
+
export declare class CollectUseCase {
|
|
7
|
+
private reader;
|
|
8
|
+
private summarizer;
|
|
9
|
+
private filter;
|
|
10
|
+
private repository;
|
|
11
|
+
constructor(reader: AgentLogReader, summarizer: Summarizer, filter: PrivacyFilter, repository: FileSystemRepository);
|
|
12
|
+
collectAll(): Promise<void>;
|
|
13
|
+
collectSession(sessionId: string): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
export declare function parseSkillSession(turns: ConversationTurn[]): StepDraft | null;
|
|
16
|
+
export declare function parsePlanText(prompt: string): StepDraft | null;
|