action-items 1.0.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 ADDED
@@ -0,0 +1,32 @@
1
+ # action-items
2
+
3
+ Extract structured action items from transcripts, documents, and message threads.
4
+
5
+ ## Features
6
+
7
+ - returns typed JSON
8
+ - captures assignee, due date, priority, and source context
9
+ - optimized for messy human text rather than idealized inputs
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install action-items
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```ts
20
+ import { createActionItemExtractor } from "action-items";
21
+
22
+ const extract = createActionItemExtractor({
23
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY!,
24
+ });
25
+
26
+ const items = await extract({
27
+ title: "Weekly Ops Review",
28
+ content: transcript,
29
+ });
30
+ ```
31
+
32
+ Good for meeting bots, task capture workflows, and document triage tools.
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "action-items",
3
+ "version": "1.0.0",
4
+ "description": "Extract structured action items from documents, transcripts, and messages using Claude",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "typecheck": "tsc --noEmit --pretty false"
19
+ },
20
+ "keywords": ["action-items", "extraction", "ai", "claude", "haiku", "meetings", "transcripts"],
21
+ "devDependencies": {
22
+ "@types/node": "^22.0.0",
23
+ "typescript": "^5"
24
+ }
25
+ }
package/src/index.ts ADDED
@@ -0,0 +1,124 @@
1
+ /**
2
+ * action-items
3
+ *
4
+ * Extract structured action items from documents, transcripts, and messages
5
+ * using Claude Haiku. Returns JSON-typed results ready to store or display.
6
+ *
7
+ * Usage:
8
+ * import { createActionItemExtractor } from "action-items";
9
+ *
10
+ * const extract = createActionItemExtractor({
11
+ * anthropicApiKey: process.env.ANTHROPIC_API_KEY!,
12
+ * });
13
+ *
14
+ * const items = await extract({ title: "Q1 Planning", content: transcript });
15
+ */
16
+
17
+ export interface ActionItem {
18
+ /** Imperative description: "Schedule weekly sync with engineering team" */
19
+ description: string;
20
+ /** Name or role if mentioned, else null */
21
+ assignee: string | null;
22
+ /** ISO date (YYYY-MM-DD) if mentioned, else null */
23
+ due_date: string | null;
24
+ priority: "high" | "medium" | "low";
25
+ /** Relevant quote from source for traceability */
26
+ context: string | null;
27
+ }
28
+
29
+ export interface ActionItemExtractorConfig {
30
+ anthropicApiKey: string;
31
+ /** Claude model to use — default claude-haiku-4-5-20251001 */
32
+ model?: string;
33
+ /** Max characters of content to send to the model — default 8000 */
34
+ maxContentLength?: number;
35
+ }
36
+
37
+ export type ActionItemExtractFn = (params: {
38
+ title: string;
39
+ content: string;
40
+ }) => Promise<ActionItem[]>;
41
+
42
+ const SYSTEM_PROMPT = `You are an operations analyst assistant. Your job is to extract concrete action items from meeting transcripts, documents, and messages.
43
+
44
+ Rules:
45
+ - Only extract items with a clear owner or assignee, or where the action is concrete and unambiguous
46
+ - Ignore vague statements, general observations, or background context
47
+ - Extract the immediate next action, not high-level goals
48
+ - If a due date is mentioned, extract it in ISO format (YYYY-MM-DD)
49
+ - Priority: "high" if urgent/blocking, "medium" if near-term, "low" if long-term or nice-to-have
50
+ - Context: include the relevant sentence or short paragraph from the source for traceability
51
+ - Return ONLY valid JSON, no prose`;
52
+
53
+ /**
54
+ * Create an action item extractor bound to your Anthropic API key and config.
55
+ */
56
+ export function createActionItemExtractor(
57
+ config: ActionItemExtractorConfig,
58
+ ): ActionItemExtractFn {
59
+ const {
60
+ anthropicApiKey,
61
+ model = "claude-haiku-4-5-20251001",
62
+ maxContentLength = 8000,
63
+ } = config;
64
+
65
+ return async function extract({ title, content }): Promise<ActionItem[]> {
66
+ if (!content || content.trim().length < 50) return [];
67
+
68
+ const userPrompt = `Extract action items from this document.
69
+
70
+ Title: ${title}
71
+
72
+ Content:
73
+ ${content.slice(0, maxContentLength)}
74
+
75
+ Return a JSON array. Each item:
76
+ {
77
+ "description": "Clear action in imperative form (e.g. 'Schedule weekly sync with engineering team')",
78
+ "assignee": "Name or role if mentioned, else null",
79
+ "due_date": "YYYY-MM-DD if mentioned, else null",
80
+ "priority": "high|medium|low",
81
+ "context": "Relevant quote from source text"
82
+ }
83
+
84
+ If no clear action items exist, return [].`;
85
+
86
+ let raw: string;
87
+ try {
88
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
89
+ method: "POST",
90
+ headers: {
91
+ "Content-Type": "application/json",
92
+ "x-api-key": anthropicApiKey,
93
+ "anthropic-version": "2023-06-01",
94
+ },
95
+ body: JSON.stringify({
96
+ model,
97
+ max_tokens: 2048,
98
+ system: SYSTEM_PROMPT,
99
+ messages: [{ role: "user", content: userPrompt }],
100
+ }),
101
+ });
102
+ if (!response.ok) {
103
+ const e = await response.json().catch(() => ({})) as { error?: { message: string } };
104
+ throw new Error(e.error?.message ?? `Anthropic API error ${response.status}`);
105
+ }
106
+ const data = await response.json() as { content?: { text?: string }[] };
107
+ raw = data.content?.[0]?.text ?? "[]";
108
+ } catch (err) {
109
+ console.error("[action-items] API error:", (err as Error).message);
110
+ return [];
111
+ }
112
+
113
+ // Strip markdown fences if present
114
+ const cleaned = raw.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
115
+
116
+ try {
117
+ const items = JSON.parse(cleaned);
118
+ return Array.isArray(items) ? (items as ActionItem[]) : [];
119
+ } catch {
120
+ console.warn("[action-items] Failed to parse response:", cleaned.slice(0, 200));
121
+ return [];
122
+ }
123
+ };
124
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./dist",
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "sourceMap": true,
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true
13
+ },
14
+ "include": ["src"]
15
+ }