@cydm/pie 1.0.6 → 1.0.8
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 +156 -9
- package/dist/builtin/extensions/ask-user/index.js +2 -3
- package/dist/builtin/extensions/init/index.js +70 -68
- package/dist/builtin/extensions/kimi-attachments/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +85 -87
- package/dist/builtin/extensions/subagent/index.js +17 -7
- package/dist/builtin/extensions/todo/index.js +51 -22
- package/dist/builtin/skills/browser-tools/CHANGELOG.md +2 -44
- package/dist/builtin/skills/browser-tools/README.md +10 -99
- package/dist/builtin/skills/browser-tools/SKILL.md +21 -174
- package/dist/builtin/skills/browser-tools/package.json +6 -13
- package/dist/builtin/skills/browser-tools/playwright-cli.js +24 -0
- package/dist/builtin/skills/skill-creator/SKILL.md +17 -17
- package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.mjs +285 -0
- package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +1 -1
- package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.mjs +271 -0
- package/dist/builtin/skills/skill-creator/scripts/claude_cli.mjs +115 -0
- package/dist/builtin/skills/skill-creator/scripts/generate_report.mjs +224 -0
- package/dist/builtin/skills/skill-creator/scripts/improve_description.mjs +198 -0
- package/dist/builtin/skills/skill-creator/scripts/package_skill.mjs +132 -0
- package/dist/builtin/skills/skill-creator/scripts/pie_runner.mjs +115 -0
- package/dist/builtin/skills/skill-creator/scripts/quick_validate.mjs +44 -0
- package/dist/builtin/skills/skill-creator/scripts/run_eval.mjs +169 -0
- package/dist/builtin/skills/skill-creator/scripts/run_loop.mjs +297 -0
- package/dist/builtin/skills/skill-creator/scripts/skill_metadata.mjs +134 -0
- package/dist/chunks/chunk-6WD2NFIC.js +8383 -0
- package/dist/chunks/{chunk-MWFBYJOI.js → chunk-A5JSJAPK.js} +3973 -1313
- package/dist/chunks/chunk-NTYHFBUA.js +36 -0
- package/dist/chunks/chunk-ZRONUKTW.js +989 -0
- package/dist/chunks/{src-EGWRDMLB.js → src-3X3HBT2G.js} +1 -2
- package/dist/chunks/typescript-GSKWJIO4.js +210747 -0
- package/dist/cli.js +15261 -12502
- package/models.schema.json +238 -0
- package/package.json +34 -8
- package/dist/builtin/skills/browser-tools/browser-content.js +0 -103
- package/dist/builtin/skills/browser-tools/browser-cookies.js +0 -35
- package/dist/builtin/skills/browser-tools/browser-eval.js +0 -49
- package/dist/builtin/skills/browser-tools/browser-hn-scraper.js +0 -108
- package/dist/builtin/skills/browser-tools/browser-nav.js +0 -44
- package/dist/builtin/skills/browser-tools/browser-pick.js +0 -162
- package/dist/builtin/skills/browser-tools/browser-screenshot.js +0 -34
- package/dist/builtin/skills/browser-tools/browser-start.js +0 -86
- package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.py +0 -471
- package/dist/builtin/skills/skill-creator/scripts/__init__.py +0 -0
- package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/dist/builtin/skills/skill-creator/scripts/generate_report.py +0 -326
- package/dist/builtin/skills/skill-creator/scripts/improve_description.py +0 -247
- package/dist/builtin/skills/skill-creator/scripts/package_skill.py +0 -136
- package/dist/builtin/skills/skill-creator/scripts/quick_validate.py +0 -103
- package/dist/builtin/skills/skill-creator/scripts/run_eval.py +0 -310
- package/dist/builtin/skills/skill-creator/scripts/run_loop.py +0 -328
- package/dist/builtin/skills/skill-creator/scripts/utils.py +0 -47
- package/dist/chunks/capabilities-FENCOHVA.js +0 -9
- package/dist/chunks/chunk-JYBXCEJJ.js +0 -315
- package/dist/chunks/chunk-RID3574D.js +0 -2718
- package/dist/chunks/chunk-TBJ25UWB.js +0 -3657
- package/dist/chunks/chunk-XZXLO7YB.js +0 -322
- package/dist/chunks/file-logger-AL5VVZHH.js +0 -22
- package/dist/chunks/src-WRUACRN2.js +0 -132
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://cydream.tech/schemas/pie/models.schema.json",
|
|
4
|
+
"title": "Pie models.json",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"profiles": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"description": "User-defined endpoint profiles. Runtime only loads models from this map.",
|
|
11
|
+
"minProperties": 1,
|
|
12
|
+
"additionalProperties": {
|
|
13
|
+
"$ref": "#/$defs/profile"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"defaults": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"properties": {
|
|
20
|
+
"provider": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"description": "Default profile key."
|
|
24
|
+
},
|
|
25
|
+
"modelId": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1,
|
|
28
|
+
"description": "Default model id within the selected profile."
|
|
29
|
+
},
|
|
30
|
+
"modelClasses": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"properties": {
|
|
34
|
+
"light": { "$ref": "#/$defs/modelClass" },
|
|
35
|
+
"balanced": { "$ref": "#/$defs/modelClass" },
|
|
36
|
+
"strong": { "$ref": "#/$defs/modelClass" }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"toolModels": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"properties": {
|
|
43
|
+
"web_search": { "$ref": "#/$defs/modelClass" },
|
|
44
|
+
"read_file.image": { "$ref": "#/$defs/modelClass" },
|
|
45
|
+
"read_file.video": { "$ref": "#/$defs/modelClass" },
|
|
46
|
+
"read_file.audio": { "$ref": "#/$defs/modelClass" },
|
|
47
|
+
"read_file.document": { "$ref": "#/$defs/modelClass" }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"required": ["profiles"],
|
|
54
|
+
"$defs": {
|
|
55
|
+
"cost": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"additionalProperties": false,
|
|
58
|
+
"properties": {
|
|
59
|
+
"input": { "type": "number" },
|
|
60
|
+
"output": { "type": "number" },
|
|
61
|
+
"cacheRead": { "type": "number" },
|
|
62
|
+
"cacheWrite": { "type": "number" }
|
|
63
|
+
},
|
|
64
|
+
"required": ["input", "output", "cacheRead", "cacheWrite"]
|
|
65
|
+
},
|
|
66
|
+
"cacheCapability": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": false,
|
|
69
|
+
"properties": {
|
|
70
|
+
"mode": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"enum": ["none", "session_store", "prompt_cache", "usage_only"]
|
|
73
|
+
},
|
|
74
|
+
"supported": { "type": "boolean" },
|
|
75
|
+
"supportsUsageMetrics": { "type": "boolean" },
|
|
76
|
+
"description": { "type": "string" }
|
|
77
|
+
},
|
|
78
|
+
"required": ["mode", "supported"]
|
|
79
|
+
},
|
|
80
|
+
"modelClass": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"properties": {
|
|
84
|
+
"provider": { "type": "string", "minLength": 1 },
|
|
85
|
+
"modelId": { "type": "string", "minLength": 1 }
|
|
86
|
+
},
|
|
87
|
+
"required": ["provider", "modelId"]
|
|
88
|
+
},
|
|
89
|
+
"webSearch": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"additionalProperties": false,
|
|
92
|
+
"properties": {
|
|
93
|
+
"type": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"enum": ["anthropic_server_tool", "chat_completions_web_search", "openai_responses"]
|
|
96
|
+
},
|
|
97
|
+
"forceToolChoice": { "type": "boolean" },
|
|
98
|
+
"searchEngine": { "type": "string", "minLength": 1 },
|
|
99
|
+
"count": { "type": "integer", "minimum": 1 },
|
|
100
|
+
"contentSize": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"enum": ["low", "medium", "high"]
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"required": ["type"]
|
|
106
|
+
},
|
|
107
|
+
"fileCapabilityValue": {
|
|
108
|
+
"oneOf": [
|
|
109
|
+
{ "type": "boolean" },
|
|
110
|
+
{
|
|
111
|
+
"type": "object",
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"properties": {
|
|
114
|
+
"supported": { "type": "boolean" },
|
|
115
|
+
"formats": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"items": { "type": "string", "minLength": 1 },
|
|
118
|
+
"uniqueItems": true
|
|
119
|
+
},
|
|
120
|
+
"maxFileSizeMb": { "type": "number", "exclusiveMinimum": 0 },
|
|
121
|
+
"maxDurationSeconds": { "type": "number", "exclusiveMinimum": 0 }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"fileCapabilities": {
|
|
127
|
+
"type": "object",
|
|
128
|
+
"additionalProperties": false,
|
|
129
|
+
"properties": {
|
|
130
|
+
"image": { "$ref": "#/$defs/fileCapabilityValue" },
|
|
131
|
+
"video": { "$ref": "#/$defs/fileCapabilityValue" },
|
|
132
|
+
"audio": { "$ref": "#/$defs/fileCapabilityValue" },
|
|
133
|
+
"document": { "$ref": "#/$defs/fileCapabilityValue" }
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"compat": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"additionalProperties": false,
|
|
139
|
+
"properties": {
|
|
140
|
+
"supportsStore": { "type": "boolean" },
|
|
141
|
+
"supportsDeveloperRole": { "type": "boolean" },
|
|
142
|
+
"supportsReasoningEffort": { "type": "boolean" },
|
|
143
|
+
"supportsUsageInStreaming": { "type": "boolean" },
|
|
144
|
+
"maxTokensField": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"enum": ["max_completion_tokens", "max_tokens"]
|
|
147
|
+
},
|
|
148
|
+
"requiresToolResultName": { "type": "boolean" },
|
|
149
|
+
"requiresAssistantAfterToolResult": { "type": "boolean" },
|
|
150
|
+
"requiresThinkingAsText": { "type": "boolean" },
|
|
151
|
+
"supportsStrictMode": { "type": "boolean" },
|
|
152
|
+
"cacheCapability": { "$ref": "#/$defs/cacheCapability" }
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"headers": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"propertyNames": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"minLength": 1
|
|
160
|
+
},
|
|
161
|
+
"additionalProperties": {
|
|
162
|
+
"type": "string"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"model": {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"additionalProperties": false,
|
|
168
|
+
"properties": {
|
|
169
|
+
"id": { "type": "string", "minLength": 1 },
|
|
170
|
+
"name": { "type": "string", "minLength": 1 },
|
|
171
|
+
"reasoning": { "type": "boolean" },
|
|
172
|
+
"input": {
|
|
173
|
+
"type": "array",
|
|
174
|
+
"minItems": 1,
|
|
175
|
+
"uniqueItems": true,
|
|
176
|
+
"items": {
|
|
177
|
+
"type": "string",
|
|
178
|
+
"enum": ["text", "image", "audio", "video"]
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"cost": { "$ref": "#/$defs/cost" },
|
|
182
|
+
"contextWindow": { "type": "integer", "minimum": 1 },
|
|
183
|
+
"maxTokens": { "type": "integer", "minimum": 1 },
|
|
184
|
+
"compat": { "$ref": "#/$defs/compat" },
|
|
185
|
+
"cacheCapability": { "$ref": "#/$defs/cacheCapability" },
|
|
186
|
+
"webSearch": { "$ref": "#/$defs/webSearch" },
|
|
187
|
+
"fileCapabilities": { "$ref": "#/$defs/fileCapabilities" },
|
|
188
|
+
"headers": { "$ref": "#/$defs/headers" },
|
|
189
|
+
"apiKeyEnv": { "type": "string", "minLength": 1 },
|
|
190
|
+
"displayName": { "type": "string", "minLength": 1 },
|
|
191
|
+
"filePlatform": { "type": "string", "minLength": 1 },
|
|
192
|
+
"attachmentPlatform": { "type": "string", "minLength": 1 }
|
|
193
|
+
},
|
|
194
|
+
"required": ["id", "input", "cost", "contextWindow", "maxTokens"]
|
|
195
|
+
},
|
|
196
|
+
"profile": {
|
|
197
|
+
"type": "object",
|
|
198
|
+
"additionalProperties": false,
|
|
199
|
+
"properties": {
|
|
200
|
+
"baseUrl": { "type": "string", "minLength": 1 },
|
|
201
|
+
"api": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"enum": ["openai-completions", "anthropic-messages"]
|
|
204
|
+
},
|
|
205
|
+
"apiKey": { "type": "string", "minLength": 1 },
|
|
206
|
+
"apiKeyEnv": { "type": "string", "minLength": 1 },
|
|
207
|
+
"headers": { "$ref": "#/$defs/headers" },
|
|
208
|
+
"displayName": { "type": "string", "minLength": 1 },
|
|
209
|
+
"filePlatform": { "type": "string", "minLength": 1 },
|
|
210
|
+
"attachmentPlatform": { "type": "string", "minLength": 1 },
|
|
211
|
+
"compat": { "$ref": "#/$defs/compat" },
|
|
212
|
+
"cacheCapability": { "$ref": "#/$defs/cacheCapability" },
|
|
213
|
+
"webSearch": { "$ref": "#/$defs/webSearch" },
|
|
214
|
+
"fileCapabilities": { "$ref": "#/$defs/fileCapabilities" },
|
|
215
|
+
"models": {
|
|
216
|
+
"type": "array",
|
|
217
|
+
"minItems": 1,
|
|
218
|
+
"items": { "$ref": "#/$defs/model" }
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
"required": ["api", "baseUrl", "models"],
|
|
222
|
+
"anyOf": [
|
|
223
|
+
{ "required": ["apiKey"] },
|
|
224
|
+
{ "required": ["apiKeyEnv"] },
|
|
225
|
+
{
|
|
226
|
+
"properties": {
|
|
227
|
+
"models": {
|
|
228
|
+
"contains": {
|
|
229
|
+
"type": "object",
|
|
230
|
+
"required": ["apiKeyEnv"]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cydm/pie",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Pie AI Agent CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,18 +9,41 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"clean": "rm -rf dist",
|
|
11
11
|
"build": "node scripts/build-release.mjs",
|
|
12
|
+
"check:types:strict": "tsc -p tsconfig.strict.json",
|
|
12
13
|
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
13
14
|
"start": "node dist/cli.js",
|
|
15
|
+
"init:models": "tsx scripts/init-models-config.ts",
|
|
16
|
+
"validate:models": "tsx scripts/validate-models-config.ts",
|
|
14
17
|
"test": "npm run test:offline",
|
|
15
18
|
"pretest:offline": "npm run build --workspace @pie/agent-framework && npm run build --workspace @pie/shared-headless-capabilities && npm run build",
|
|
16
|
-
"test:offline": "node --test --import tsx test/core-services.test.ts test/cli.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-extension.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/hierarchical-command-system.test.ts test/message-queue-unit.test.ts test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/viewport-position-final.test.ts",
|
|
19
|
+
"test:offline": "node --test --import tsx test/core-services.test.ts test/cli.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-extension.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/hierarchical-command-system.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/code-intel-typescript-provider.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/tool-name-rendering.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/daily-agent-smoke.terminal.test.ts test/viewport-position-final.test.ts",
|
|
20
|
+
"test:todo-tui": "PIE_REAL_TODO_TUI=1 node --test --import tsx test/todo-closure.terminal.test.ts",
|
|
21
|
+
"test:daily-tui": "npm run test:daily-tui:quick",
|
|
22
|
+
"test:daily-tui:quick": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_TUI_LEVEL=quick node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
23
|
+
"test:daily-tui:full": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_TUI_LEVEL=full node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
24
|
+
"test:daily-tui:quick:repeat": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=quick node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
25
|
+
"test:daily-tui:full:repeat": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=full node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
26
|
+
"test:daily-gate:quick": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=quick PIE_DAILY_REPEAT=1 node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
27
|
+
"test:daily-gate:full": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=full PIE_DAILY_REPEAT=1 node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
28
|
+
"test:daily-gate:mock": "PIE_DAILY_MOCK_GATE=1 node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
29
|
+
"test:daily-gate:quick:repeat:stable": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=quick PIE_DAILY_REPEAT=3 node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
30
|
+
"test:daily-gate:quick:repeat": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=quick node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
31
|
+
"test:daily-gate:full:repeat": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_REPEAT_MODE=full node --test --import tsx test/daily-agent-smoke.terminal.test.ts",
|
|
17
32
|
"test:kimi-smoke": "node scripts/kimi-attachment-smoke.mjs",
|
|
18
33
|
"test:integration": "node --test --import tsx test/cli.test.ts test/compact-e2e.test.ts test/file-upload-test.terminal.test.ts test/human-simulation.test.ts test/interactive-integration.test.ts test/pie-cli.terminal.test.ts test/txt-upload-test.terminal.test.ts",
|
|
19
34
|
"test:fixes": "tsx test-fixes.ts",
|
|
35
|
+
"eval": "tsx evals/runner.ts",
|
|
36
|
+
"eval:task": "tsx evals/runner.ts --layer=task",
|
|
37
|
+
"eval:dev": "tsx evals/runner.ts --layer=task --dataset=dev",
|
|
38
|
+
"eval:core": "tsx evals/runner.ts --layer=task --dataset=core",
|
|
39
|
+
"eval:dev:compare": "tsx evals/runner.ts --layer=task --dataset=dev",
|
|
40
|
+
"eval:core:compare": "tsx evals/runner.ts --layer=task --dataset=core",
|
|
41
|
+
"eval:cognitive": "tsx evals/run.ts",
|
|
20
42
|
"pack:check": "npm pack --dry-run"
|
|
21
43
|
},
|
|
22
44
|
"files": [
|
|
23
45
|
"dist/**/*",
|
|
46
|
+
"models.schema.json",
|
|
24
47
|
"README.md"
|
|
25
48
|
],
|
|
26
49
|
"publishConfig": {
|
|
@@ -39,11 +62,13 @@
|
|
|
39
62
|
},
|
|
40
63
|
"dependencies": {
|
|
41
64
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
42
|
-
"@
|
|
65
|
+
"@playwright/cli": "^0.1.7",
|
|
66
|
+
"@sinclair/typebox": "^0.34.49",
|
|
43
67
|
"cli-highlight": "^2.1.11",
|
|
44
68
|
"diff": "8.0.3",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
69
|
+
"jszip": "^3.10.1",
|
|
70
|
+
"koffi": "^2.15.6",
|
|
71
|
+
"yaml": "^2.8.3"
|
|
47
72
|
},
|
|
48
73
|
"devDependencies": {
|
|
49
74
|
"@pie/agent-core": "*",
|
|
@@ -51,11 +76,12 @@
|
|
|
51
76
|
"@pie/ai": "*",
|
|
52
77
|
"@pie/shared-headless-capabilities": "*",
|
|
53
78
|
"@pie/tui": "*",
|
|
54
|
-
"@types/node": "^22.10.5",
|
|
55
79
|
"@types/diff": "7.0.2",
|
|
56
|
-
"
|
|
80
|
+
"@types/node": "^22.10.5",
|
|
81
|
+
"esbuild": "^0.28.0",
|
|
82
|
+
"node-pty": "^1.1.0",
|
|
57
83
|
"tsx": "^4.20.3",
|
|
58
84
|
"typescript": "^5.7.3",
|
|
59
|
-
"vitest": "
|
|
85
|
+
"vitest": "4.0.18"
|
|
60
86
|
}
|
|
61
87
|
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import puppeteer from "puppeteer-core";
|
|
4
|
-
import { Readability } from "@mozilla/readability";
|
|
5
|
-
import { JSDOM } from "jsdom";
|
|
6
|
-
import TurndownService from "turndown";
|
|
7
|
-
import { gfm } from "turndown-plugin-gfm";
|
|
8
|
-
|
|
9
|
-
// Global timeout - exit if script takes too long
|
|
10
|
-
const TIMEOUT = 30000;
|
|
11
|
-
const timeoutId = setTimeout(() => {
|
|
12
|
-
console.error("✗ Timeout after 30s");
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}, TIMEOUT).unref();
|
|
15
|
-
|
|
16
|
-
const url = process.argv[2];
|
|
17
|
-
|
|
18
|
-
if (!url) {
|
|
19
|
-
console.log("Usage: browser-content.js <url>");
|
|
20
|
-
console.log("\nExtracts readable content from a URL as markdown.");
|
|
21
|
-
console.log("\nExamples:");
|
|
22
|
-
console.log(" browser-content.js https://example.com");
|
|
23
|
-
console.log(" browser-content.js https://en.wikipedia.org/wiki/Rust_(programming_language)");
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const b = await Promise.race([
|
|
28
|
-
puppeteer.connect({
|
|
29
|
-
browserURL: "http://localhost:9222",
|
|
30
|
-
defaultViewport: null,
|
|
31
|
-
}),
|
|
32
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5000)),
|
|
33
|
-
]).catch((e) => {
|
|
34
|
-
console.error("✗ Could not connect to browser:", e.message);
|
|
35
|
-
console.error(" Run: browser-start.js");
|
|
36
|
-
process.exit(1);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const p = (await b.pages()).at(-1);
|
|
40
|
-
if (!p) {
|
|
41
|
-
console.error("✗ No active tab found");
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
await Promise.race([
|
|
46
|
-
p.goto(url, { waitUntil: "networkidle2" }),
|
|
47
|
-
new Promise((r) => setTimeout(r, 10000)),
|
|
48
|
-
]).catch(() => {});
|
|
49
|
-
|
|
50
|
-
// Get HTML via CDP (works even with TrustedScriptURL restrictions)
|
|
51
|
-
const client = await p.createCDPSession();
|
|
52
|
-
const { root } = await client.send("DOM.getDocument", { depth: -1, pierce: true });
|
|
53
|
-
const { outerHTML } = await client.send("DOM.getOuterHTML", { nodeId: root.nodeId });
|
|
54
|
-
await client.detach();
|
|
55
|
-
|
|
56
|
-
const finalUrl = p.url();
|
|
57
|
-
|
|
58
|
-
// Extract with Readability
|
|
59
|
-
const doc = new JSDOM(outerHTML, { url: finalUrl });
|
|
60
|
-
const reader = new Readability(doc.window.document);
|
|
61
|
-
const article = reader.parse();
|
|
62
|
-
|
|
63
|
-
// Convert to markdown
|
|
64
|
-
function htmlToMarkdown(html) {
|
|
65
|
-
const turndown = new TurndownService({ headingStyle: "atx", codeBlockStyle: "fenced" });
|
|
66
|
-
turndown.use(gfm);
|
|
67
|
-
turndown.addRule("removeEmptyLinks", {
|
|
68
|
-
filter: (node) => node.nodeName === "A" && !node.textContent?.trim(),
|
|
69
|
-
replacement: () => "",
|
|
70
|
-
});
|
|
71
|
-
return turndown
|
|
72
|
-
.turndown(html)
|
|
73
|
-
.replace(/\[\\?\[\s*\\?\]\]\([^)]*\)/g, "")
|
|
74
|
-
.replace(/ +/g, " ")
|
|
75
|
-
.replace(/\s+,/g, ",")
|
|
76
|
-
.replace(/\s+\./g, ".")
|
|
77
|
-
.replace(/\n{3,}/g, "\n\n")
|
|
78
|
-
.trim();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let content;
|
|
82
|
-
if (article && article.content) {
|
|
83
|
-
content = htmlToMarkdown(article.content);
|
|
84
|
-
} else {
|
|
85
|
-
// Fallback
|
|
86
|
-
const fallbackDoc = new JSDOM(outerHTML, { url: finalUrl });
|
|
87
|
-
const fallbackBody = fallbackDoc.window.document;
|
|
88
|
-
fallbackBody.querySelectorAll("script, style, noscript, nav, header, footer, aside").forEach((el) => el.remove());
|
|
89
|
-
const main = fallbackBody.querySelector("main, article, [role='main'], .content, #content") || fallbackBody.body;
|
|
90
|
-
const fallbackHtml = main?.innerHTML || "";
|
|
91
|
-
if (fallbackHtml.trim().length > 100) {
|
|
92
|
-
content = htmlToMarkdown(fallbackHtml);
|
|
93
|
-
} else {
|
|
94
|
-
content = "(Could not extract content)";
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
console.log(`URL: ${finalUrl}`);
|
|
99
|
-
if (article?.title) console.log(`Title: ${article.title}`);
|
|
100
|
-
console.log("");
|
|
101
|
-
console.log(content);
|
|
102
|
-
|
|
103
|
-
process.exit(0);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import puppeteer from "puppeteer-core";
|
|
4
|
-
|
|
5
|
-
const b = await Promise.race([
|
|
6
|
-
puppeteer.connect({
|
|
7
|
-
browserURL: "http://localhost:9222",
|
|
8
|
-
defaultViewport: null,
|
|
9
|
-
}),
|
|
10
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5000)),
|
|
11
|
-
]).catch((e) => {
|
|
12
|
-
console.error("✗ Could not connect to browser:", e.message);
|
|
13
|
-
console.error(" Run: browser-start.js");
|
|
14
|
-
process.exit(1);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const p = (await b.pages()).at(-1);
|
|
18
|
-
|
|
19
|
-
if (!p) {
|
|
20
|
-
console.error("✗ No active tab found");
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const cookies = await p.cookies();
|
|
25
|
-
|
|
26
|
-
for (const cookie of cookies) {
|
|
27
|
-
console.log(`${cookie.name}: ${cookie.value}`);
|
|
28
|
-
console.log(` domain: ${cookie.domain}`);
|
|
29
|
-
console.log(` path: ${cookie.path}`);
|
|
30
|
-
console.log(` httpOnly: ${cookie.httpOnly}`);
|
|
31
|
-
console.log(` secure: ${cookie.secure}`);
|
|
32
|
-
console.log("");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
await b.disconnect();
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import puppeteer from "puppeteer-core";
|
|
2
|
-
|
|
3
|
-
const code = process.argv.slice(2).join(" ");
|
|
4
|
-
if (!code) {
|
|
5
|
-
console.log("Usage: browser-eval.js code");
|
|
6
|
-
process.exit(1);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const browser = await puppeteer.connect({
|
|
10
|
-
browserURL: "http://localhost:9222",
|
|
11
|
-
defaultViewport: null,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const page = (await browser.pages()).at(-1);
|
|
15
|
-
|
|
16
|
-
if (!page) {
|
|
17
|
-
console.error("No active tab");
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const result = await page.evaluate((userCode) => {
|
|
23
|
-
try {
|
|
24
|
-
return eval(userCode);
|
|
25
|
-
} catch (e) {
|
|
26
|
-
return {__error: e.message};
|
|
27
|
-
}
|
|
28
|
-
}, code);
|
|
29
|
-
|
|
30
|
-
if (result && result.__error) {
|
|
31
|
-
console.error("Error:", result.__error);
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (result === undefined) {
|
|
36
|
-
console.log("undefined");
|
|
37
|
-
} else if (result === null) {
|
|
38
|
-
console.log("null");
|
|
39
|
-
} else if (typeof result === "object") {
|
|
40
|
-
console.log(JSON.stringify(result));
|
|
41
|
-
} else {
|
|
42
|
-
console.log(result);
|
|
43
|
-
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error("Error:", error.message);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
} finally {
|
|
48
|
-
await browser.disconnect();
|
|
49
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Hacker News Scraper
|
|
5
|
-
*
|
|
6
|
-
* Fetches and parses submissions from Hacker News front page.
|
|
7
|
-
* Usage: node browser-hn-scraper.js [--limit <number>]
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import * as cheerio from 'cheerio';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Scrapes Hacker News front page
|
|
14
|
-
* @param {number} limit - Maximum number of submissions to return (default: 30)
|
|
15
|
-
* @returns {Promise<Array>} Array of submission objects
|
|
16
|
-
*/
|
|
17
|
-
async function scrapeHackerNews(limit = 30) {
|
|
18
|
-
const url = 'https://news.ycombinator.com';
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const response = await fetch(url);
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const html = await response.text();
|
|
27
|
-
const $ = cheerio.load(html);
|
|
28
|
-
const submissions = [];
|
|
29
|
-
|
|
30
|
-
// Each submission has class 'athing'
|
|
31
|
-
$('.athing').each((index, element) => {
|
|
32
|
-
if (submissions.length >= limit) return false; // Stop when limit reached
|
|
33
|
-
|
|
34
|
-
const $element = $(element);
|
|
35
|
-
const id = $element.attr('id');
|
|
36
|
-
|
|
37
|
-
// Get title and URL from titleline
|
|
38
|
-
const $titleLine = $element.find('.titleline > a').first();
|
|
39
|
-
const title = $titleLine.text().trim();
|
|
40
|
-
const url = $titleLine.attr('href');
|
|
41
|
-
|
|
42
|
-
// Get the next row which contains metadata (points, author, comments)
|
|
43
|
-
const $metadataRow = $element.next();
|
|
44
|
-
const $subtext = $metadataRow.find('.subtext');
|
|
45
|
-
|
|
46
|
-
// Get points
|
|
47
|
-
const $score = $subtext.find(`#score_${id}`);
|
|
48
|
-
const pointsText = $score.text();
|
|
49
|
-
const points = pointsText ? parseInt(pointsText.match(/\d+/)?.[0] || '0') : 0;
|
|
50
|
-
|
|
51
|
-
// Get author
|
|
52
|
-
const author = $subtext.find('.hnuser').text().trim();
|
|
53
|
-
|
|
54
|
-
// Get time
|
|
55
|
-
const time = $subtext.find('.age').attr('title') || $subtext.find('.age').text().trim();
|
|
56
|
-
|
|
57
|
-
// Get comments count
|
|
58
|
-
const $commentsLink = $subtext.find('a').last();
|
|
59
|
-
const commentsText = $commentsLink.text();
|
|
60
|
-
let commentsCount = 0;
|
|
61
|
-
|
|
62
|
-
if (commentsText.includes('comment')) {
|
|
63
|
-
const match = commentsText.match(/(\d+)/);
|
|
64
|
-
commentsCount = match ? parseInt(match[0]) : 0;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
submissions.push({
|
|
68
|
-
id,
|
|
69
|
-
title,
|
|
70
|
-
url,
|
|
71
|
-
points,
|
|
72
|
-
author,
|
|
73
|
-
time,
|
|
74
|
-
comments: commentsCount,
|
|
75
|
-
hnUrl: `https://news.ycombinator.com/item?id=${id}`
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
return submissions;
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error('Error scraping Hacker News:', error.message);
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// CLI interface
|
|
87
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
88
|
-
const args = process.argv.slice(2);
|
|
89
|
-
let limit = 30;
|
|
90
|
-
|
|
91
|
-
// Parse --limit argument
|
|
92
|
-
const limitIndex = args.indexOf('--limit');
|
|
93
|
-
if (limitIndex !== -1 && args[limitIndex + 1]) {
|
|
94
|
-
limit = parseInt(args[limitIndex + 1]);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
scrapeHackerNews(limit)
|
|
98
|
-
.then(submissions => {
|
|
99
|
-
console.log(JSON.stringify(submissions, null, 2));
|
|
100
|
-
console.error(`\n✓ Scraped ${submissions.length} submissions`);
|
|
101
|
-
})
|
|
102
|
-
.catch(error => {
|
|
103
|
-
console.error('Failed to scrape:', error.message);
|
|
104
|
-
process.exit(1);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export { scrapeHackerNews };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import puppeteer from "puppeteer-core";
|
|
4
|
-
|
|
5
|
-
const args = process.argv.slice(2);
|
|
6
|
-
const newTab = args.includes("--new");
|
|
7
|
-
const reload = args.includes("--reload");
|
|
8
|
-
const url = args.find(a => !a.startsWith("--"));
|
|
9
|
-
|
|
10
|
-
if (!url) {
|
|
11
|
-
console.log("Usage: browser-nav.js <url> [--new] [--reload]");
|
|
12
|
-
console.log("\nExamples:");
|
|
13
|
-
console.log(" browser-nav.js https://example.com # Navigate current tab");
|
|
14
|
-
console.log(" browser-nav.js https://example.com --new # Open in new tab");
|
|
15
|
-
console.log(" browser-nav.js https://example.com --reload # Navigate and force reload");
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const b = await Promise.race([
|
|
20
|
-
puppeteer.connect({
|
|
21
|
-
browserURL: "http://localhost:9222",
|
|
22
|
-
defaultViewport: null,
|
|
23
|
-
}),
|
|
24
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5000)),
|
|
25
|
-
]).catch((e) => {
|
|
26
|
-
console.error("✗ Could not connect to browser:", e.message);
|
|
27
|
-
console.error(" Run: browser-start.js");
|
|
28
|
-
process.exit(1);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
if (newTab) {
|
|
32
|
-
const p = await b.newPage();
|
|
33
|
-
await p.goto(url, { waitUntil: "domcontentloaded" });
|
|
34
|
-
console.log("✓ Opened:", url);
|
|
35
|
-
} else {
|
|
36
|
-
const p = (await b.pages()).at(-1);
|
|
37
|
-
await p.goto(url, { waitUntil: "domcontentloaded" });
|
|
38
|
-
if (reload) {
|
|
39
|
-
await p.reload({ waitUntil: "domcontentloaded" });
|
|
40
|
-
}
|
|
41
|
-
console.log("✓ Navigated to:", url);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await b.disconnect();
|