feat: add 5 research tools and blocks framework setup
- Add @tpmjs/tools-page-brief for URL content extraction - Add @tpmjs/tools-compare-pages for cross-source validation - Add @tpmjs/tools-source-credibility for credibility scoring - Add @tpmjs/tools-claim-checklist for factual claim extraction - Add @tpmjs/tools-timeline-from-text for timeline generation - Move createBlogPost to packages/tools/official/ - Add blocks.yml for Blocks framework validation - Update pnpm-workspace.yaml to include official tools
This commit is contained in:
parent
409d1232a6
commit
36a0735ab1
34 changed files with 2458 additions and 61 deletions
21
.changeset/add-research-tools.md
Normal file
21
.changeset/add-research-tools.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
"@tpmjs/tools-page-brief": minor
|
||||||
|
"@tpmjs/tools-compare-pages": minor
|
||||||
|
"@tpmjs/tools-source-credibility": minor
|
||||||
|
"@tpmjs/tools-claim-checklist": minor
|
||||||
|
"@tpmjs/tools-timeline-from-text": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add 5 new research tools for AI-powered content analysis
|
||||||
|
|
||||||
|
New tools using AI SDK v6 beta (tool() + jsonSchema() pattern):
|
||||||
|
|
||||||
|
- **@tpmjs/tools-page-brief**: Fetch URL and extract summary with key points and claims needing citations
|
||||||
|
- **@tpmjs/tools-compare-pages**: Compare two URLs for agreements, conflicts, and unique points
|
||||||
|
- **@tpmjs/tools-source-credibility**: Calculate heuristic credibility score based on domain signals
|
||||||
|
- **@tpmjs/tools-claim-checklist**: Extract checkable factual claims from text
|
||||||
|
- **@tpmjs/tools-timeline-from-text**: Extract dated events and return normalized timeline
|
||||||
|
|
||||||
|
All tools are stub implementations ready for full logic implementation.
|
||||||
|
|
||||||
|
Also moved @tpmjs/createblogpost to packages/tools/official/ directory and set up blocks.yml for Blocks framework validation.
|
||||||
21
docs/TODO.md
21
docs/TODO.md
|
|
@ -130,6 +130,27 @@ GET /api/users/[username]/collections - Get user's public collections
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Benchmark Comparison Page
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
- [ ] Create `/benchmarks` page to compare tool performance
|
||||||
|
- [ ] Display execution time comparisons across similar tools
|
||||||
|
- [ ] Show token usage efficiency metrics
|
||||||
|
- [ ] Compare success rates and reliability
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- [ ] Side-by-side tool comparison UI
|
||||||
|
- [ ] Historical performance trends (charts)
|
||||||
|
- [ ] Filter by category to compare relevant tools
|
||||||
|
- [ ] Export benchmark data as JSON/CSV
|
||||||
|
|
||||||
|
### Data Collection
|
||||||
|
- [ ] Track execution metrics from playground simulations
|
||||||
|
- [ ] Aggregate anonymous performance data
|
||||||
|
- [ ] Calculate percentile rankings within categories
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Consider rate limiting on ratings to prevent abuse
|
- Consider rate limiting on ratings to prevent abuse
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.9.4",
|
"@biomejs/biome": "^1.9.4",
|
||||||
|
"@blocksai/cli": "^0.2.1",
|
||||||
|
"@blocksai/validators": "^1.1.1",
|
||||||
"@changesets/cli": "^2.27.10",
|
"@changesets/cli": "^2.27.10",
|
||||||
"@total-typescript/ts-reset": "^0.6.1",
|
"@total-typescript/ts-reset": "^0.6.1",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.10.2",
|
||||||
|
|
|
||||||
3
packages/tools/official/.gitignore
vendored
Normal file
3
packages/tools/official/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Blocks CLI runtime files
|
||||||
|
.blocks/
|
||||||
|
.env
|
||||||
168
packages/tools/official/BLOCKS_DOMAIN_VALIDATOR_BUG.md
Normal file
168
packages/tools/official/BLOCKS_DOMAIN_VALIDATOR_BUG.md
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Blocks Domain Validator Bug Report
|
||||||
|
|
||||||
|
## Status: FIXED
|
||||||
|
|
||||||
|
The fix has been applied to `/Users/ajaxdavis/repos/blocks/packages/ai/src/provider.ts`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The domain validator in `@blocksai/validators` was failing with an OpenAI structured output schema error when validating any block. The schema and shape.ts validators worked correctly.
|
||||||
|
|
||||||
|
## Error Message
|
||||||
|
|
||||||
|
```
|
||||||
|
⚠ [domain] AI validation failed: Invalid schema for response_format 'response':
|
||||||
|
In context=('properties', 'issues', 'items'), 'required' is required to be supplied
|
||||||
|
and to be an array including every key in properties. Missing 'file'.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
- `@blocksai/cli`: latest (installed via npx)
|
||||||
|
- `@blocksai/validators`: latest
|
||||||
|
- OpenAI API: Using `OPENAI_API_KEY` from .env
|
||||||
|
- Node.js: v22.x
|
||||||
|
- OS: macOS
|
||||||
|
|
||||||
|
## Reproduction Steps
|
||||||
|
|
||||||
|
1. Create a valid `blocks.yml` with any block definition
|
||||||
|
2. Create the corresponding TypeScript file with proper exports
|
||||||
|
3. Run `npx blocks run --all`
|
||||||
|
|
||||||
|
## Example blocks.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: "tpmjs-official-tools"
|
||||||
|
root: "."
|
||||||
|
|
||||||
|
philosophy:
|
||||||
|
- "Tools must be pure functions with no side effects"
|
||||||
|
|
||||||
|
domain:
|
||||||
|
entities:
|
||||||
|
url:
|
||||||
|
fields: [href, domain, protocol, path]
|
||||||
|
|
||||||
|
signals:
|
||||||
|
credibility:
|
||||||
|
description: "Trustworthiness of a source"
|
||||||
|
|
||||||
|
measures:
|
||||||
|
valid_output:
|
||||||
|
constraints:
|
||||||
|
- "Must return structured object matching interface"
|
||||||
|
|
||||||
|
blocks:
|
||||||
|
domain_rules:
|
||||||
|
- id: pure_function
|
||||||
|
description: "Tool must be deterministic with no side effects"
|
||||||
|
|
||||||
|
research.pageBrief:
|
||||||
|
description: "Fetch URL and extract content"
|
||||||
|
path: "page-brief"
|
||||||
|
inputs:
|
||||||
|
- name: url
|
||||||
|
type: string
|
||||||
|
outputs:
|
||||||
|
- name: brief
|
||||||
|
type: PageBrief
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
validators:
|
||||||
|
- schema
|
||||||
|
- shape.ts
|
||||||
|
- domain
|
||||||
|
```
|
||||||
|
|
||||||
|
## Observed Behavior
|
||||||
|
|
||||||
|
```
|
||||||
|
📦 Validating: research.pageBrief
|
||||||
|
✓ schema ok
|
||||||
|
✓ shape.ts ok
|
||||||
|
- Running domain...
|
||||||
|
⚠ [domain] AI validation failed: Invalid schema for response_format 'response':
|
||||||
|
In context=('properties', 'issues', 'items'), 'required' is required to be
|
||||||
|
supplied and to be an array including every key in properties. Missing 'file'.
|
||||||
|
|
||||||
|
⚠️ Block "research.pageBrief" has warnings
|
||||||
|
```
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
The error message indicates that the domain validator is constructing an OpenAI structured output request with a JSON schema that's missing required fields. Specifically:
|
||||||
|
|
||||||
|
1. OpenAI's structured output feature requires that all properties in an object schema must be listed in the `required` array
|
||||||
|
2. The domain validator's internal response schema has a `file` property in the `issues.items` object
|
||||||
|
3. This `file` property is not included in the corresponding `required` array
|
||||||
|
|
||||||
|
This is an internal schema construction issue within the domain validator, not related to user-provided blocks.yml configuration.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
The domain validator should:
|
||||||
|
1. Construct a valid JSON schema for OpenAI's structured output API
|
||||||
|
2. Ensure all properties are listed in `required` arrays
|
||||||
|
3. Successfully analyze the block against the domain rules and philosophy
|
||||||
|
|
||||||
|
## Workaround
|
||||||
|
|
||||||
|
Currently, the schema and shape.ts validators work correctly. The domain validator can be skipped by removing `domain` from the validators list in blocks.yml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
validators:
|
||||||
|
- schema
|
||||||
|
- shape.ts
|
||||||
|
# - domain # Disabled due to bug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fix Applied
|
||||||
|
|
||||||
|
**File:** `/Users/ajaxdavis/repos/blocks/packages/ai/src/provider.ts` (lines 163-173)
|
||||||
|
|
||||||
|
**Before (broken):**
|
||||||
|
```typescript
|
||||||
|
const schema = z.object({
|
||||||
|
isValid: z.boolean(),
|
||||||
|
issues: z.array(
|
||||||
|
z.object({
|
||||||
|
message: z.string(),
|
||||||
|
severity: z.enum(["error", "warning"]),
|
||||||
|
file: z.string().optional(), // ← Problem: .optional() excludes from required
|
||||||
|
})
|
||||||
|
),
|
||||||
|
summary: z.string().optional().describe("..."),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**After (fixed):**
|
||||||
|
```typescript
|
||||||
|
const schema = z.object({
|
||||||
|
isValid: z.boolean(),
|
||||||
|
issues: z.array(
|
||||||
|
z.object({
|
||||||
|
message: z.string().describe("Description of the issue found"),
|
||||||
|
severity: z.enum(["error", "warning"]).describe("Severity of the issue"),
|
||||||
|
file: z.string().describe("File path where the issue was found, or empty string if not file-specific"),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
summary: z.string().describe("Brief summary of why the block passed or failed validation"),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Root Cause:** OpenAI's structured output requires ALL properties to be in the JSON schema's `required` array. When Zod converts `.optional()` to JSON schema, it omits that property from `required`, causing OpenAI to reject the schema.
|
||||||
|
|
||||||
|
**Solution:** Remove `.optional()` and `.default()` modifiers. Make all fields required strings. The AI will return an empty string for file-agnostic issues.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- **Severity**: Medium - domain validation is non-functional
|
||||||
|
- **Affected**: All blocks using the domain validator
|
||||||
|
- **Workaround available**: Yes - disable domain validator
|
||||||
|
|
||||||
|
## Additional Context
|
||||||
|
|
||||||
|
This was tested with 6 different blocks, all showing the same error. The error is consistent and reproducible regardless of block configuration.
|
||||||
132
packages/tools/official/blocks.yml
Normal file
132
packages/tools/official/blocks.yml
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
name: "tpmjs-official-tools"
|
||||||
|
root: "."
|
||||||
|
|
||||||
|
philosophy:
|
||||||
|
- "Tools must be pure functions with no side effects"
|
||||||
|
- "Each tool solves one specific problem well"
|
||||||
|
- "Tools are publishable to npm as @tpmjs/* packages"
|
||||||
|
- "Use AI SDK v6 tool() + jsonSchema() pattern"
|
||||||
|
|
||||||
|
domain:
|
||||||
|
entities:
|
||||||
|
url:
|
||||||
|
fields: [href, domain, protocol, path]
|
||||||
|
text:
|
||||||
|
fields: [content, sentences, wordCount]
|
||||||
|
claim:
|
||||||
|
fields: [statement, needsCitation, evidence]
|
||||||
|
timeline_event:
|
||||||
|
fields: [date, description, confidence]
|
||||||
|
|
||||||
|
signals:
|
||||||
|
credibility:
|
||||||
|
description: "Trustworthiness of a source"
|
||||||
|
extraction_hint: "Look for author, date, citations, HTTPS"
|
||||||
|
readability:
|
||||||
|
description: "How easy content is to understand"
|
||||||
|
extraction_hint: "Check sentence length, jargon, structure"
|
||||||
|
|
||||||
|
measures:
|
||||||
|
valid_output:
|
||||||
|
constraints:
|
||||||
|
- "Must return structured object matching interface"
|
||||||
|
- "Must not throw unhandled errors"
|
||||||
|
npm_publishable:
|
||||||
|
constraints:
|
||||||
|
- "Must have valid package.json with tpmjs field"
|
||||||
|
- "Must export tool as named and default export"
|
||||||
|
|
||||||
|
blocks:
|
||||||
|
domain_rules:
|
||||||
|
- id: pure_function
|
||||||
|
description: "Tool must be deterministic with no side effects"
|
||||||
|
- id: ai_sdk_pattern
|
||||||
|
description: "Must use AI SDK v6 tool() + jsonSchema()"
|
||||||
|
- id: npm_ready
|
||||||
|
description: "Must be publishable to npm with complete metadata"
|
||||||
|
|
||||||
|
adapter.createBlogPost:
|
||||||
|
description: "Creates structured blog posts with frontmatter and metadata"
|
||||||
|
path: "createBlogPost"
|
||||||
|
inputs:
|
||||||
|
- name: title
|
||||||
|
type: string
|
||||||
|
- name: author
|
||||||
|
type: string
|
||||||
|
- name: content
|
||||||
|
type: string
|
||||||
|
- name: tags
|
||||||
|
type: string[]
|
||||||
|
optional: true
|
||||||
|
- name: format
|
||||||
|
type: "'markdown' | 'mdx'"
|
||||||
|
optional: true
|
||||||
|
outputs:
|
||||||
|
- name: blogPost
|
||||||
|
type: BlogPost
|
||||||
|
measures: [valid_output, npm_publishable]
|
||||||
|
|
||||||
|
research.pageBrief:
|
||||||
|
description: "Fetch URL, extract main content, return summary with key points and claims needing citations"
|
||||||
|
path: "page-brief"
|
||||||
|
inputs:
|
||||||
|
- name: url
|
||||||
|
type: string
|
||||||
|
outputs:
|
||||||
|
- name: brief
|
||||||
|
type: PageBrief
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
research.comparePages:
|
||||||
|
description: "Compare two URLs for agreements, conflicts, and unique points"
|
||||||
|
path: "compare-pages"
|
||||||
|
inputs:
|
||||||
|
- name: urlA
|
||||||
|
type: string
|
||||||
|
- name: urlB
|
||||||
|
type: string
|
||||||
|
outputs:
|
||||||
|
- name: comparison
|
||||||
|
type: PageComparison
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
research.sourceCredibility:
|
||||||
|
description: "Heuristic credibility score based on domain signals, author presence, citations"
|
||||||
|
path: "source-credibility"
|
||||||
|
inputs:
|
||||||
|
- name: url
|
||||||
|
type: string
|
||||||
|
- name: html
|
||||||
|
type: string
|
||||||
|
optional: true
|
||||||
|
outputs:
|
||||||
|
- name: credibility
|
||||||
|
type: CredibilityScore
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
research.claimChecklist:
|
||||||
|
description: "Extract checkable factual claims from text, mark what needs citations"
|
||||||
|
path: "claim-checklist"
|
||||||
|
inputs:
|
||||||
|
- name: text
|
||||||
|
type: string
|
||||||
|
outputs:
|
||||||
|
- name: checklist
|
||||||
|
type: ClaimChecklist
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
research.timelineFromText:
|
||||||
|
description: "Extract dated events from text, return normalized timeline with confidence"
|
||||||
|
path: "timeline-from-text"
|
||||||
|
inputs:
|
||||||
|
- name: text
|
||||||
|
type: string
|
||||||
|
outputs:
|
||||||
|
- name: timeline
|
||||||
|
type: Timeline
|
||||||
|
measures: [valid_output]
|
||||||
|
|
||||||
|
validators:
|
||||||
|
- schema
|
||||||
|
- shape.ts
|
||||||
|
- domain
|
||||||
61
packages/tools/official/claim-checklist/package.json
Normal file
61
packages/tools/official/claim-checklist/package.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"name": "@tpmjs/tools-claim-checklist",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Extract checkable factual claims from text and identify what needs citations",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": ["tpmjs", "research", "ai", "claims", "fact-checking", "citations"],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist .turbo"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tpmjs/tsconfig": "workspace:*",
|
||||||
|
"tsup": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anthropics/tpmjs.git",
|
||||||
|
"directory": "packages/tools/official/claim-checklist"
|
||||||
|
},
|
||||||
|
"homepage": "https://tpmjs.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"tpmjs": {
|
||||||
|
"category": "research",
|
||||||
|
"frameworks": ["vercel-ai"],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "claimChecklistTool",
|
||||||
|
"description": "Extract checkable factual claims from text and mark what needs citations",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "text",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The text to analyze for factual claims",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": {
|
||||||
|
"type": "ClaimChecklist",
|
||||||
|
"description": "Object with claims array and summary statistics"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ai": "6.0.0-beta.124",
|
||||||
|
"sbd": "^1.0.19"
|
||||||
|
}
|
||||||
|
}
|
||||||
56
packages/tools/official/claim-checklist/src/index.ts
Normal file
56
packages/tools/official/claim-checklist/src/index.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { jsonSchema, tool } from 'ai';
|
||||||
|
|
||||||
|
export interface ClaimChecklist {
|
||||||
|
originalText: string;
|
||||||
|
claims: Array<{
|
||||||
|
claim: string;
|
||||||
|
needsCitation: boolean;
|
||||||
|
evidenceType: 'statistic' | 'fact' | 'quote' | 'opinion' | 'common-knowledge';
|
||||||
|
suggestedEvidence: string;
|
||||||
|
sentenceIndex: number;
|
||||||
|
}>;
|
||||||
|
summary: {
|
||||||
|
totalClaims: number;
|
||||||
|
needingCitation: number;
|
||||||
|
verified: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClaimChecklistInput = {
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const claimChecklistTool = tool({
|
||||||
|
description:
|
||||||
|
'Extract checkable factual claims from text, mark what needs citations, and suggest what evidence would support each claim',
|
||||||
|
inputSchema: jsonSchema<ClaimChecklistInput>({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'The text to analyze for factual claims',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['text'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}),
|
||||||
|
async execute({ text }): Promise<ClaimChecklist> {
|
||||||
|
// TODO: Implement with:
|
||||||
|
// 1. Split text into sentences with sbd
|
||||||
|
// 2. Rule-based claim extraction (numbers, dates, proper nouns)
|
||||||
|
// 3. Classify claim types
|
||||||
|
// 4. Determine if citation needed based on type
|
||||||
|
|
||||||
|
return {
|
||||||
|
originalText: text,
|
||||||
|
claims: [],
|
||||||
|
summary: {
|
||||||
|
totalClaims: 0,
|
||||||
|
needingCitation: 0,
|
||||||
|
verified: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default claimChecklistTool;
|
||||||
67
packages/tools/official/compare-pages/package.json
Normal file
67
packages/tools/official/compare-pages/package.json
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"name": "@tpmjs/tools-compare-pages",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Compare two URLs for agreements, conflicts, and unique points for cross-source validation",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": ["tpmjs", "research", "ai", "comparison", "fact-checking"],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist .turbo"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tpmjs/tsconfig": "workspace:*",
|
||||||
|
"tsup": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anthropics/tpmjs.git",
|
||||||
|
"directory": "packages/tools/official/compare-pages"
|
||||||
|
},
|
||||||
|
"homepage": "https://tpmjs.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"tpmjs": {
|
||||||
|
"category": "research",
|
||||||
|
"frameworks": ["vercel-ai"],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "comparePagesTool",
|
||||||
|
"description": "Compare two URLs for agreements, conflicts, and unique points",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "urlA",
|
||||||
|
"type": "string",
|
||||||
|
"description": "First URL to compare",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "urlB",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Second URL to compare",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": {
|
||||||
|
"type": "PageComparison",
|
||||||
|
"description": "Object with agreements, conflicts, uniqueToA, and uniqueToB arrays"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ai": "6.0.0-beta.124",
|
||||||
|
"natural": "^8.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
57
packages/tools/official/compare-pages/src/index.ts
Normal file
57
packages/tools/official/compare-pages/src/index.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { jsonSchema, tool } from 'ai';
|
||||||
|
|
||||||
|
export interface PageComparison {
|
||||||
|
urlA: string;
|
||||||
|
urlB: string;
|
||||||
|
agreements: string[];
|
||||||
|
conflicts: Array<{
|
||||||
|
topic: string;
|
||||||
|
pageAPosition: string;
|
||||||
|
pageBPosition: string;
|
||||||
|
}>;
|
||||||
|
uniqueToA: string[];
|
||||||
|
uniqueToB: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type ComparePagesInput = {
|
||||||
|
urlA: string;
|
||||||
|
urlB: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const comparePagesTool = tool({
|
||||||
|
description:
|
||||||
|
'Compare two URLs for agreements, conflicts, and unique points to help with cross-source validation',
|
||||||
|
inputSchema: jsonSchema<ComparePagesInput>({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
urlA: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'First URL to compare',
|
||||||
|
},
|
||||||
|
urlB: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Second URL to compare',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['urlA', 'urlB'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}),
|
||||||
|
async execute({ urlA, urlB }): Promise<PageComparison> {
|
||||||
|
// TODO: Implement with:
|
||||||
|
// 1. Call pageBriefTool on both URLs
|
||||||
|
// 2. Extract key points from both
|
||||||
|
// 3. Use TF-IDF (natural) for semantic matching
|
||||||
|
// 4. Identify agreements, conflicts, and unique points
|
||||||
|
|
||||||
|
return {
|
||||||
|
urlA,
|
||||||
|
urlB,
|
||||||
|
agreements: [],
|
||||||
|
conflicts: [],
|
||||||
|
uniqueToA: [],
|
||||||
|
uniqueToB: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default comparePagesTool;
|
||||||
11
packages/tools/official/compare-pages/tsconfig.json
Normal file
11
packages/tools/official/compare-pages/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"extends": "@tpmjs/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"incremental": false,
|
||||||
|
"composite": false
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
10
packages/tools/official/compare-pages/tsup.config.ts
Normal file
10
packages/tools/official/compare-pages/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
dts: true,
|
||||||
|
clean: true,
|
||||||
|
treeshake: true,
|
||||||
|
splitting: false,
|
||||||
|
});
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ajaxdavis/tpmjs.git",
|
"url": "https://github.com/ajaxdavis/tpmjs.git",
|
||||||
"directory": "packages/tools/createBlogPost"
|
"directory": "packages/tools/official/createBlogPost"
|
||||||
},
|
},
|
||||||
"homepage": "https://tpmjs.com",
|
"homepage": "https://tpmjs.com",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
11
packages/tools/official/createBlogPost/tsconfig.json
Normal file
11
packages/tools/official/createBlogPost/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"extends": "@tpmjs/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"incremental": false,
|
||||||
|
"composite": false
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
10
packages/tools/official/createBlogPost/tsup.config.ts
Normal file
10
packages/tools/official/createBlogPost/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
dts: true,
|
||||||
|
clean: true,
|
||||||
|
treeshake: true,
|
||||||
|
splitting: false,
|
||||||
|
});
|
||||||
63
packages/tools/official/page-brief/package.json
Normal file
63
packages/tools/official/page-brief/package.json
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"name": "@tpmjs/tools-page-brief",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Fetch a URL, extract main content, and return a brief with summary, key points, and claims needing citations",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": ["tpmjs", "research", "ai", "readability", "web-scraping"],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist .turbo"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tpmjs/tsconfig": "workspace:*",
|
||||||
|
"tsup": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anthropics/tpmjs.git",
|
||||||
|
"directory": "packages/tools/official/page-brief"
|
||||||
|
},
|
||||||
|
"homepage": "https://tpmjs.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"tpmjs": {
|
||||||
|
"category": "research",
|
||||||
|
"frameworks": ["vercel-ai"],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "pageBriefTool",
|
||||||
|
"description": "Fetch a URL, extract main content, and return a brief with summary, key points, and claims needing citations",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The URL to fetch and analyze",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": {
|
||||||
|
"type": "PageBrief",
|
||||||
|
"description": "Object with url, title, summary, keyPoints array, and claimsNeedingCitation array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ai": "6.0.0-beta.124",
|
||||||
|
"@mozilla/readability": "^0.5.0",
|
||||||
|
"jsdom": "^26.0.0",
|
||||||
|
"sbd": "^1.0.19"
|
||||||
|
}
|
||||||
|
}
|
||||||
50
packages/tools/official/page-brief/src/index.ts
Normal file
50
packages/tools/official/page-brief/src/index.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { jsonSchema, tool } from 'ai';
|
||||||
|
|
||||||
|
export interface PageBrief {
|
||||||
|
url: string;
|
||||||
|
title: string;
|
||||||
|
summary: string;
|
||||||
|
keyPoints: string[];
|
||||||
|
claimsNeedingCitation: Array<{
|
||||||
|
claim: string;
|
||||||
|
suggestedEvidence: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageBriefInput = {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pageBriefTool = tool({
|
||||||
|
description:
|
||||||
|
'Fetch a URL, extract main content using readability, and return a brief with summary, key points, and claims that need citations',
|
||||||
|
inputSchema: jsonSchema<PageBriefInput>({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
url: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'The URL to fetch and analyze',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['url'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}),
|
||||||
|
async execute({ url }): Promise<PageBrief> {
|
||||||
|
// TODO: Implement with fetch + @mozilla/readability + jsdom + sbd
|
||||||
|
// 1. Fetch the URL
|
||||||
|
// 2. Parse HTML with jsdom
|
||||||
|
// 3. Extract main content with Readability
|
||||||
|
// 4. Split into sentences with sbd
|
||||||
|
// 5. Identify claims that need citations
|
||||||
|
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
title: 'Not implemented',
|
||||||
|
summary: 'This is a stub implementation. Real implementation will use @mozilla/readability.',
|
||||||
|
keyPoints: [],
|
||||||
|
claimsNeedingCitation: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default pageBriefTool;
|
||||||
11
packages/tools/official/page-brief/tsconfig.json
Normal file
11
packages/tools/official/page-brief/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"extends": "@tpmjs/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"incremental": false,
|
||||||
|
"composite": false
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
10
packages/tools/official/page-brief/tsup.config.ts
Normal file
10
packages/tools/official/page-brief/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
dts: true,
|
||||||
|
clean: true,
|
||||||
|
treeshake: true,
|
||||||
|
splitting: false,
|
||||||
|
});
|
||||||
68
packages/tools/official/source-credibility/package.json
Normal file
68
packages/tools/official/source-credibility/package.json
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"name": "@tpmjs/tools-source-credibility",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Calculate heuristic credibility score based on domain signals, author presence, and citations",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": ["tpmjs", "research", "ai", "credibility", "fact-checking"],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist .turbo"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tpmjs/tsconfig": "workspace:*",
|
||||||
|
"tsup": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anthropics/tpmjs.git",
|
||||||
|
"directory": "packages/tools/official/source-credibility"
|
||||||
|
},
|
||||||
|
"homepage": "https://tpmjs.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"tpmjs": {
|
||||||
|
"category": "research",
|
||||||
|
"frameworks": ["vercel-ai"],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "sourceCredibilityTool",
|
||||||
|
"description": "Calculate heuristic credibility score based on domain signals",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"type": "string",
|
||||||
|
"description": "URL to analyze for credibility",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "html",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional pre-fetched HTML content",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": {
|
||||||
|
"type": "CredibilityScore",
|
||||||
|
"description": "Object with score (0-1), signals breakdown, and detailed analysis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ai": "6.0.0-beta.124",
|
||||||
|
"tldts": "^6.1.0",
|
||||||
|
"cheerio": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
75
packages/tools/official/source-credibility/src/index.ts
Normal file
75
packages/tools/official/source-credibility/src/index.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { jsonSchema, tool } from 'ai';
|
||||||
|
|
||||||
|
export interface CredibilityScore {
|
||||||
|
url: string;
|
||||||
|
score: number; // 0.0 to 1.0
|
||||||
|
signals: {
|
||||||
|
hasHttps: boolean;
|
||||||
|
hasAuthor: boolean;
|
||||||
|
hasPublishDate: boolean;
|
||||||
|
hasCitations: boolean;
|
||||||
|
domainAge?: string;
|
||||||
|
isKnownSource: boolean;
|
||||||
|
};
|
||||||
|
breakdown: Array<{
|
||||||
|
signal: string;
|
||||||
|
weight: number;
|
||||||
|
present: boolean;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SourceCredibilityInput = {
|
||||||
|
url: string;
|
||||||
|
html?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sourceCredibilityTool = tool({
|
||||||
|
description:
|
||||||
|
'Calculate a heuristic credibility score based on domain signals, author presence, date, citations density, and HTTPS',
|
||||||
|
inputSchema: jsonSchema<SourceCredibilityInput>({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
url: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'URL to analyze for credibility',
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Optional: pre-fetched HTML content to analyze',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['url'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}),
|
||||||
|
async execute({ url, html: _html }): Promise<CredibilityScore> {
|
||||||
|
// TODO: Implement with:
|
||||||
|
// 1. Parse URL with tldts for domain info
|
||||||
|
// 2. If no HTML provided, fetch the page
|
||||||
|
// 3. Parse HTML with cheerio for meta signals
|
||||||
|
// 4. Check for author, date, citations
|
||||||
|
// 5. Calculate weighted score
|
||||||
|
|
||||||
|
const isHttps = url.startsWith('https://');
|
||||||
|
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
score: 0.5, // Stub score
|
||||||
|
signals: {
|
||||||
|
hasHttps: isHttps,
|
||||||
|
hasAuthor: false,
|
||||||
|
hasPublishDate: false,
|
||||||
|
hasCitations: false,
|
||||||
|
isKnownSource: false,
|
||||||
|
},
|
||||||
|
breakdown: [
|
||||||
|
{ signal: 'https', weight: 0.1, present: isHttps },
|
||||||
|
{ signal: 'author', weight: 0.2, present: false },
|
||||||
|
{ signal: 'publishDate', weight: 0.2, present: false },
|
||||||
|
{ signal: 'citations', weight: 0.3, present: false },
|
||||||
|
{ signal: 'knownSource', weight: 0.2, present: false },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default sourceCredibilityTool;
|
||||||
11
packages/tools/official/source-credibility/tsconfig.json
Normal file
11
packages/tools/official/source-credibility/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"extends": "@tpmjs/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"incremental": false,
|
||||||
|
"composite": false
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
10
packages/tools/official/source-credibility/tsup.config.ts
Normal file
10
packages/tools/official/source-credibility/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
dts: true,
|
||||||
|
clean: true,
|
||||||
|
treeshake: true,
|
||||||
|
splitting: false,
|
||||||
|
});
|
||||||
62
packages/tools/official/timeline-from-text/package.json
Normal file
62
packages/tools/official/timeline-from-text/package.json
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"name": "@tpmjs/tools-timeline-from-text",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Extract dated events from text and return a normalized timeline with confidence scores",
|
||||||
|
"type": "module",
|
||||||
|
"keywords": ["tpmjs", "research", "ai", "timeline", "dates", "events"],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist .turbo"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tpmjs/tsconfig": "workspace:*",
|
||||||
|
"tsup": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anthropics/tpmjs.git",
|
||||||
|
"directory": "packages/tools/official/timeline-from-text"
|
||||||
|
},
|
||||||
|
"homepage": "https://tpmjs.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"tpmjs": {
|
||||||
|
"category": "research",
|
||||||
|
"frameworks": ["vercel-ai"],
|
||||||
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "timelineFromTextTool",
|
||||||
|
"description": "Extract dated events from text and return normalized timeline",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "text",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The text to extract timeline events from",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": {
|
||||||
|
"type": "Timeline",
|
||||||
|
"description": "Object with events array and optional date range"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ai": "6.0.0-beta.124",
|
||||||
|
"chrono-node": "^2.7.0",
|
||||||
|
"sbd": "^1.0.19"
|
||||||
|
}
|
||||||
|
}
|
||||||
50
packages/tools/official/timeline-from-text/src/index.ts
Normal file
50
packages/tools/official/timeline-from-text/src/index.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { jsonSchema, tool } from 'ai';
|
||||||
|
|
||||||
|
export interface Timeline {
|
||||||
|
originalText: string;
|
||||||
|
events: Array<{
|
||||||
|
date: string; // ISO format
|
||||||
|
description: string;
|
||||||
|
confidence: number; // 0.0 to 1.0
|
||||||
|
originalMention: string;
|
||||||
|
}>;
|
||||||
|
dateRange?: {
|
||||||
|
earliest: string;
|
||||||
|
latest: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimelineFromTextInput = {
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const timelineFromTextTool = tool({
|
||||||
|
description:
|
||||||
|
'Extract dated events from text and return a normalized timeline with confidence scores per event',
|
||||||
|
inputSchema: jsonSchema<TimelineFromTextInput>({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'The text to extract timeline events from',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['text'],
|
||||||
|
additionalProperties: false,
|
||||||
|
}),
|
||||||
|
async execute({ text }): Promise<Timeline> {
|
||||||
|
// TODO: Implement with:
|
||||||
|
// 1. Use chrono-node to parse dates from text
|
||||||
|
// 2. Extract sentence context around each date
|
||||||
|
// 3. Normalize dates to ISO format
|
||||||
|
// 4. Assign confidence based on date specificity
|
||||||
|
|
||||||
|
return {
|
||||||
|
originalText: text,
|
||||||
|
events: [],
|
||||||
|
dateRange: undefined,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default timelineFromTextTool;
|
||||||
11
packages/tools/official/timeline-from-text/tsconfig.json
Normal file
11
packages/tools/official/timeline-from-text/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"extends": "@tpmjs/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"rootDir": "src",
|
||||||
|
"incremental": false,
|
||||||
|
"composite": false
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
10
packages/tools/official/timeline-from-text/tsup.config.ts
Normal file
10
packages/tools/official/timeline-from-text/tsup.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
dts: true,
|
||||||
|
clean: true,
|
||||||
|
treeshake: true,
|
||||||
|
splitting: false,
|
||||||
|
});
|
||||||
1455
pnpm-lock.yaml
generated
1455
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -5,3 +5,4 @@ packages:
|
||||||
- 'packages/config/tailwind'
|
- 'packages/config/tailwind'
|
||||||
- 'packages/config/tsconfig'
|
- 'packages/config/tsconfig'
|
||||||
- 'packages/tools/*'
|
- 'packages/tools/*'
|
||||||
|
- 'packages/tools/official/*'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue