@arnilo/prism-tools 0.0.0-stage → 0.13.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/CHANGELOG.md +410 -0
- package/LICENSE +21 -0
- package/README.md +44 -2
- package/browser/README.md +98 -0
- package/browser/skills/browser-automation/SKILL.md +14 -0
- package/browser/src/actions/cdp.ts +131 -0
- package/browser/src/actions/dialog.ts +25 -0
- package/browser/src/actions/download_release.ts +22 -0
- package/browser/src/actions/index.ts +37 -0
- package/browser/src/actions/locator.ts +70 -0
- package/browser/src/actions/navigate.ts +23 -0
- package/browser/src/actions/screenshot.ts +27 -0
- package/browser/src/actions/scroll.ts +24 -0
- package/browser/src/actions/select_page.ts +21 -0
- package/browser/src/actions/types.ts +114 -0
- package/browser/src/actions/upload.ts +44 -0
- package/browser/src/actions/wait.ts +45 -0
- package/browser/src/browser.ts +197 -0
- package/browser/src/cdp.ts +178 -0
- package/browser/src/checkpoint.ts +189 -0
- package/browser/src/config.ts +72 -0
- package/browser/src/downloads.ts +253 -0
- package/browser/src/errors.ts +31 -0
- package/browser/src/evaluate.ts +101 -0
- package/browser/src/index.ts +129 -0
- package/browser/src/limits.ts +271 -0
- package/browser/src/manager.ts +730 -0
- package/browser/src/network.ts +263 -0
- package/browser/src/observe.ts +178 -0
- package/browser/src/policy.ts +133 -0
- package/browser/src/screenshot.ts +107 -0
- package/browser/src/shared-sandbox.ts +53 -0
- package/browser/src/snapshot.ts +99 -0
- package/browser/src/targets.ts +165 -0
- package/browser/src/tools.ts +480 -0
- package/browser/src/types.ts +316 -0
- package/browser/src/uploads.ts +174 -0
- package/coding/README.md +337 -0
- package/coding/src/agent/acp-operations.ts +146 -0
- package/coding/src/agent/artifacts.ts +38 -0
- package/coding/src/agent/ask-user-decision.ts +623 -0
- package/coding/src/agent/atomic-write.ts +23 -0
- package/coding/src/agent/bounded-file.ts +21 -0
- package/coding/src/agent/checks.ts +301 -0
- package/coding/src/agent/coding-checkpoint.ts +828 -0
- package/coding/src/agent/delete.ts +237 -0
- package/coding/src/agent/diagnostics-tool.ts +163 -0
- package/coding/src/agent/diagnostics.ts +262 -0
- package/coding/src/agent/edit-diff.ts +382 -0
- package/coding/src/agent/edit.ts +322 -0
- package/coding/src/agent/effects.ts +102 -0
- package/coding/src/agent/env.ts +28 -0
- package/coding/src/agent/execution-policy.ts +89 -0
- package/coding/src/agent/file-mutation-queue.ts +72 -0
- package/coding/src/agent/forge/github.ts +603 -0
- package/coding/src/agent/forge/index.ts +16 -0
- package/coding/src/agent/forge/types.ts +185 -0
- package/coding/src/agent/git-aware-repository.ts +305 -0
- package/coding/src/agent/git-exec.ts +326 -0
- package/coding/src/agent/git-status.ts +177 -0
- package/coding/src/agent/git-tools.ts +360 -0
- package/coding/src/agent/git.ts +1074 -0
- package/coding/src/agent/glob-match.ts +146 -0
- package/coding/src/agent/glob.ts +182 -0
- package/coding/src/agent/goal-verify.ts +385 -0
- package/coding/src/agent/grep-worker.ts +74 -0
- package/coding/src/agent/grep.ts +459 -0
- package/coding/src/agent/identity.ts +48 -0
- package/coding/src/agent/index.ts +676 -0
- package/coding/src/agent/language/client.ts +429 -0
- package/coding/src/agent/language/framing.ts +190 -0
- package/coding/src/agent/language/index.ts +23 -0
- package/coding/src/agent/language/intelligence.ts +682 -0
- package/coding/src/agent/language/types.ts +187 -0
- package/coding/src/agent/lifecycle-events.ts +121 -0
- package/coding/src/agent/lifecycle.ts +166 -0
- package/coding/src/agent/limits.ts +214 -0
- package/coding/src/agent/move.ts +178 -0
- package/coding/src/agent/mutation-path.ts +52 -0
- package/coding/src/agent/output-accumulator.ts +304 -0
- package/coding/src/agent/path-utils.ts +120 -0
- package/coding/src/agent/process/index.ts +58 -0
- package/coding/src/agent/process/recovery.ts +508 -0
- package/coding/src/agent/process/sessions-host.ts +222 -0
- package/coding/src/agent/process/sessions-monitor.ts +141 -0
- package/coding/src/agent/process/sessions-recovery.ts +241 -0
- package/coding/src/agent/process/sessions-spawn.ts +613 -0
- package/coding/src/agent/process/sessions-teardown.ts +281 -0
- package/coding/src/agent/process/sessions.ts +30 -0
- package/coding/src/agent/process/types.ts +358 -0
- package/coding/src/agent/read-path-set.ts +126 -0
- package/coding/src/agent/read.ts +713 -0
- package/coding/src/agent/repository/glob.ts +147 -0
- package/coding/src/agent/repository/indexed-search.ts +480 -0
- package/coding/src/agent/repository/list.ts +131 -0
- package/coding/src/agent/repository/operations.ts +22 -0
- package/coding/src/agent/repository/path.ts +98 -0
- package/coding/src/agent/repository/search.ts +277 -0
- package/coding/src/agent/repository/types.ts +243 -0
- package/coding/src/agent/repository/walk.ts +126 -0
- package/coding/src/agent/repository.ts +12 -0
- package/coding/src/agent/shell-background.ts +264 -0
- package/coding/src/agent/shell-output.ts +75 -0
- package/coding/src/agent/shell.ts +526 -0
- package/coding/src/agent/todo.ts +399 -0
- package/coding/src/agent/truncate.ts +251 -0
- package/coding/src/agent/write.ts +170 -0
- package/coding/src/ask-user-host.ts +48 -0
- package/coding/src/config.ts +278 -0
- package/coding/src/hard-deny.ts +97 -0
- package/coding/src/index.ts +318 -0
- package/coding/src/principal-guard.ts +84 -0
- package/coding/src/sandbox.ts +92 -0
- package/coding/src/security/approval.ts +144 -0
- package/coding/src/security/command-rules.ts +57 -0
- package/coding/src/security/docker-cli.ts +222 -0
- package/coding/src/security/docker-sandbox.ts +1205 -0
- package/coding/src/security/e2b-sandbox.ts +853 -0
- package/coding/src/security/egress/dns-pin.ts +88 -0
- package/coding/src/security/egress/index.ts +32 -0
- package/coding/src/security/egress/limits.ts +57 -0
- package/coding/src/security/egress/policy.ts +137 -0
- package/coding/src/security/egress/proxy.ts +599 -0
- package/coding/src/security/egress/types.ts +30 -0
- package/coding/src/security/index.ts +199 -0
- package/coding/src/security/native-sandbox.ts +639 -0
- package/coding/src/security/path-containment.ts +55 -0
- package/coding/src/security/sandbox-coding-operations.ts +392 -0
- package/coding/src/security/sandbox-fs-operations.ts +644 -0
- package/coding/src/security/sandbox-limits.ts +147 -0
- package/coding/src/security/sandbox-tar.ts +308 -0
- package/coding/src/security/sandbox.ts +179 -0
- package/coding/src/security/semaphore.ts +55 -0
- package/coding/src/targets.ts +110 -0
- package/coding/src/workspace/diff.ts +78 -0
- package/coding/src/workspace/errors.ts +28 -0
- package/coding/src/workspace/index.ts +5 -0
- package/coding/src/workspace/merge.ts +151 -0
- package/coding/src/workspace/routing.ts +76 -0
- package/coding/src/workspace/service.ts +545 -0
- package/computer-use/README.md +105 -0
- package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
- package/computer-use/src/classify.ts +53 -0
- package/computer-use/src/command.ts +29 -0
- package/computer-use/src/config.ts +69 -0
- package/computer-use/src/create.ts +170 -0
- package/computer-use/src/devices.ts +247 -0
- package/computer-use/src/env.ts +28 -0
- package/computer-use/src/index.ts +157 -0
- package/computer-use/src/skill.ts +21 -0
- package/openapi/README.md +97 -0
- package/openapi/src/compile.ts +386 -0
- package/openapi/src/config.ts +73 -0
- package/openapi/src/errors.ts +16 -0
- package/openapi/src/execute.ts +241 -0
- package/openapi/src/index.ts +124 -0
- package/openapi/src/limits.ts +63 -0
- package/openapi/src/specs.ts +86 -0
- package/openapi/src/tools.ts +60 -0
- package/openapi/src/types.ts +61 -0
- package/package.json +171 -4
- package/research/README.md +72 -0
- package/research/skills/research-report/SKILL.md +12 -0
- package/research/skills/research-scoping/SKILL.md +10 -0
- package/research/skills/research-synthesis/SKILL.md +10 -0
- package/research/skills/source-triage/SKILL.md +10 -0
- package/research/src/check.ts +71 -0
- package/research/src/config.ts +41 -0
- package/research/src/index.ts +147 -0
- package/research/src/ledger.ts +157 -0
- package/research/src/urls.ts +21 -0
- package/web/README.md +287 -0
- package/web/skills/web-research/SKILL.md +17 -0
- package/web/src/brave.ts +66 -0
- package/web/src/cache.ts +151 -0
- package/web/src/config.ts +210 -0
- package/web/src/controls.ts +128 -0
- package/web/src/domains.ts +114 -0
- package/web/src/exa.ts +60 -0
- package/web/src/firecrawl.ts +160 -0
- package/web/src/index.ts +387 -0
- package/web/src/kagi.ts +73 -0
- package/web/src/limits.ts +55 -0
- package/web/src/native/convert.ts +84 -0
- package/web/src/native/fetch.ts +226 -0
- package/web/src/normalize.ts +131 -0
- package/web/src/obscura/cdp.ts +201 -0
- package/web/src/obscura/classify.ts +35 -0
- package/web/src/obscura/cli.ts +254 -0
- package/web/src/obscura/errors.ts +8 -0
- package/web/src/obscura/index.ts +59 -0
- package/web/src/obscura/limits.ts +92 -0
- package/web/src/obscura/mcp.ts +104 -0
- package/web/src/obscura/playwright.ts +133 -0
- package/web/src/obscura/process.ts +235 -0
- package/web/src/obscura/search-profile.ts +73 -0
- package/web/src/obscura/types.ts +48 -0
- package/web/src/obscura/web.ts +419 -0
- package/web/src/prompt-fetch.ts +88 -0
- package/web/src/render.ts +75 -0
- package/web/src/searxng.ts +78 -0
- package/web/src/slice.ts +139 -0
- package/web/src/tavily.ts +77 -0
- package/web/src/tools.ts +182 -0
- package/web/src/transport.ts +310 -0
- package/web/src/types.ts +199 -0
- package/work/README.md +77 -0
- package/work/THIRD_PARTY_NOTICES +24 -0
- package/work/docling/ocr.py +150 -0
- package/work/sandbox/Dockerfile +36 -0
- package/work/sandbox/soffice.sh +12 -0
- package/work/src/command.ts +29 -0
- package/work/src/config.ts +138 -0
- package/work/src/connectors/cli.ts +343 -0
- package/work/src/connectors/drafts.ts +647 -0
- package/work/src/connectors/errors.ts +8 -0
- package/work/src/connectors/file-bytes.ts +149 -0
- package/work/src/connectors/google-workspace-http.ts +399 -0
- package/work/src/connectors/google-workspace.ts +465 -0
- package/work/src/connectors/gws-tools.ts +378 -0
- package/work/src/connectors/http.ts +123 -0
- package/work/src/connectors/idempotency.ts +235 -0
- package/work/src/connectors/identity.ts +34 -0
- package/work/src/connectors/index.ts +93 -0
- package/work/src/connectors/limits.ts +50 -0
- package/work/src/connectors/m365-tools.ts +308 -0
- package/work/src/connectors/microsoft365-http.ts +428 -0
- package/work/src/connectors/microsoft365.ts +402 -0
- package/work/src/connectors/normalize.ts +120 -0
- package/work/src/connectors/tool-helpers.ts +398 -0
- package/work/src/connectors/tools.ts +42 -0
- package/work/src/connectors/types.ts +399 -0
- package/work/src/diagrams/canonicalize.ts +166 -0
- package/work/src/diagrams/caps.ts +52 -0
- package/work/src/diagrams/embed.ts +340 -0
- package/work/src/diagrams/errors.ts +76 -0
- package/work/src/diagrams/index.ts +81 -0
- package/work/src/diagrams/messages.ts +150 -0
- package/work/src/diagrams/origin.ts +52 -0
- package/work/src/diagrams/telemetry.ts +34 -0
- package/work/src/diagrams/xml.ts +267 -0
- package/work/src/document-extraction/index.ts +563 -0
- package/work/src/document-reader/ambient.d.ts +2 -0
- package/work/src/document-reader/errors.ts +7 -0
- package/work/src/document-reader/index.ts +181 -0
- package/work/src/document-reader/mistral-ocr.ts +318 -0
- package/work/src/document-reader/parsers.ts +171 -0
- package/work/src/documents/caps.ts +135 -0
- package/work/src/documents/diff.ts +269 -0
- package/work/src/documents/errors.ts +44 -0
- package/work/src/documents/fidelity.ts +98 -0
- package/work/src/documents/generate.ts +96 -0
- package/work/src/documents/hash.ts +8 -0
- package/work/src/documents/index.ts +14 -0
- package/work/src/documents/model-schema.ts +639 -0
- package/work/src/documents/parse.ts +252 -0
- package/work/src/documents/patch-history.ts +81 -0
- package/work/src/documents/patch.ts +476 -0
- package/work/src/documents/preview-html.ts +245 -0
- package/work/src/documents/preview.ts +227 -0
- package/work/src/documents/telemetry.ts +36 -0
- package/work/src/documents/translate/docx.ts +292 -0
- package/work/src/documents/translate/pptx.ts +304 -0
- package/work/src/documents/translate/xlsx.ts +137 -0
- package/work/src/documents/types.ts +188 -0
- package/work/src/index.ts +311 -0
- package/work/src/runtime/worker-pool-entry.ts +102 -0
- package/work/src/runtime/worker-pool.ts +267 -0
- package/work/src/sandbox/composition.ts +212 -0
- package/work/src/sandbox/image.ts +6 -0
- package/work/src/sandbox/index.ts +14 -0
- package/work/src/sheets/caps.ts +68 -0
- package/work/src/sheets/csv.ts +351 -0
- package/work/src/sheets/decimal.ts +388 -0
- package/work/src/sheets/errors.ts +52 -0
- package/work/src/sheets/index.ts +62 -0
- package/work/src/sheets/inference.ts +378 -0
- package/work/src/sheets/telemetry.ts +34 -0
- package/work/src/sheets/types.ts +162 -0
- package/work/src/sheets/xlsx.ts +388 -0
- package/work/src/skills/index.ts +8 -0
- package/work/src/skills/load.ts +43 -0
- package/work/src/tools/filesystem.ts +21 -0
- package/work/src/tools/index.ts +1 -0
- package/work/src/tools/local-filesystem.ts +33 -0
- package/work/src/tools/office.ts +311 -0
- package/work/vendor/hermes-agent/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
- package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
- package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
- package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
- package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
- package/work/vendor-lock.json +11 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { JsonObject, SecretRedactor, ToolExecutionContext } from "@arnilo/prism";
|
|
2
|
+
import type { OpenApiLimits } from "./limits.js";
|
|
3
|
+
|
|
4
|
+
export interface OpenApiCredentialInput {
|
|
5
|
+
readonly operationId: string;
|
|
6
|
+
readonly method: string;
|
|
7
|
+
readonly path: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Host-owned credential resolver. Never inline secrets in the document or options. */
|
|
11
|
+
export type OpenApiCredentialResolver = (
|
|
12
|
+
input: OpenApiCredentialInput,
|
|
13
|
+
context: ToolExecutionContext,
|
|
14
|
+
) =>
|
|
15
|
+
| { readonly headers?: Readonly<Record<string, string>>; readonly query?: Readonly<Record<string, string>> }
|
|
16
|
+
| undefined
|
|
17
|
+
| Promise<{ readonly headers?: Readonly<Record<string, string>>; readonly query?: Readonly<Record<string, string>> } | undefined>;
|
|
18
|
+
|
|
19
|
+
/** Host policy check immediately before the request; throw to deny. */
|
|
20
|
+
export type OpenApiPolicyCheck = (
|
|
21
|
+
input: OpenApiCredentialInput & { readonly args: JsonObject },
|
|
22
|
+
context: ToolExecutionContext,
|
|
23
|
+
) => void | Promise<void>;
|
|
24
|
+
|
|
25
|
+
/** Optional bounded cursor pagination. Applies only to operations whose compiled query parameters include `pageParam`. */
|
|
26
|
+
export interface OpenApiPagination {
|
|
27
|
+
/** Query parameter name carrying the page token. */
|
|
28
|
+
readonly pageParam: string;
|
|
29
|
+
/** Optional query parameter name for the page size. */
|
|
30
|
+
readonly pageSizeParam?: string;
|
|
31
|
+
/** Page size sent with every page when `pageSizeParam` is set. */
|
|
32
|
+
readonly pageSize?: number;
|
|
33
|
+
/** Dot-path to the next-page token in the JSON response. Default probes `next` then `nextPageToken`. */
|
|
34
|
+
readonly nextPath?: string;
|
|
35
|
+
/** Dot-path to the items array in the JSON response. Default `items`. */
|
|
36
|
+
readonly itemsPath?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface OpenApiToolsOptions {
|
|
40
|
+
/** OpenAPI 3.1 document as a JSON string or parsed object; byte-bounded by `maxDocumentBytes`. */
|
|
41
|
+
readonly document: string | JsonObject;
|
|
42
|
+
/** Allow-listed operationIds; only these compile into tools. */
|
|
43
|
+
readonly operations: readonly string[];
|
|
44
|
+
/** Pinned absolute base URL (https; http only for loopback hosts). Document/path/operation `servers` must share its origin. */
|
|
45
|
+
readonly server: string;
|
|
46
|
+
/** Host credential resolver; merged into request headers/query, never echoed into output. */
|
|
47
|
+
readonly credentials?: OpenApiCredentialResolver;
|
|
48
|
+
/** Prefix applied to every compiled tool name (for example `<specId>_`). The result name matches. */
|
|
49
|
+
readonly namePrefix?: string;
|
|
50
|
+
/** Host policy check before each request; throw to deny. */
|
|
51
|
+
readonly policy?: OpenApiPolicyCheck;
|
|
52
|
+
/** Applied to response text before it enters the tool result. */
|
|
53
|
+
readonly redactor?: SecretRedactor;
|
|
54
|
+
/** Optional bounded cursor pagination. */
|
|
55
|
+
readonly pagination?: OpenApiPagination;
|
|
56
|
+
/** Send `Idempotency-Key: <core idempotencyKey>` on mutating requests when the core provided one. Default false. */
|
|
57
|
+
readonly idempotencyKeyHeader?: boolean;
|
|
58
|
+
readonly limits?: OpenApiLimits;
|
|
59
|
+
/** Test seam; defaults to global fetch. */
|
|
60
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,173 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism-tools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Prism coding, web, browser, research, OpenAPI, computer-use and work tools. Import each package through its subpath.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"bun": ">=1.4.4"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/ashiqrniloy/prism.git",
|
|
13
|
+
"directory": "packages/tools"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/ashiqrniloy/prism/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/ashiqrniloy/prism/tree/main/packages/tools#readme",
|
|
19
|
+
"keywords": [
|
|
20
|
+
"prism",
|
|
21
|
+
"work",
|
|
22
|
+
"connectors",
|
|
23
|
+
"office",
|
|
24
|
+
"documents",
|
|
25
|
+
"document-reader",
|
|
26
|
+
"sheets",
|
|
27
|
+
"diagrams",
|
|
28
|
+
"docx",
|
|
29
|
+
"xlsx",
|
|
30
|
+
"pptx",
|
|
31
|
+
"drawio"
|
|
32
|
+
],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"exports": {
|
|
38
|
+
"./coding": "./coding/src/index.ts",
|
|
39
|
+
"./web": "./web/src/index.ts",
|
|
40
|
+
"./browser": "./browser/src/index.ts",
|
|
41
|
+
"./research": "./research/src/index.ts",
|
|
42
|
+
"./openapi": "./openapi/src/index.ts",
|
|
43
|
+
"./computer-use": "./computer-use/src/index.ts",
|
|
44
|
+
"./work": "./work/src/index.ts",
|
|
45
|
+
"./work/connectors": "./work/src/connectors/index.ts",
|
|
46
|
+
"./work/connectors/drafts": "./work/src/connectors/drafts.ts",
|
|
47
|
+
"./work/connectors/google-workspace": "./work/src/connectors/google-workspace.ts",
|
|
48
|
+
"./work/connectors/microsoft365": "./work/src/connectors/microsoft365.ts",
|
|
49
|
+
"./work/diagrams": "./work/src/diagrams/index.ts",
|
|
50
|
+
"./work/document-extraction": "./work/src/document-extraction/index.ts",
|
|
51
|
+
"./work/document-reader": "./work/src/document-reader/index.ts",
|
|
52
|
+
"./work/documents": "./work/src/documents/index.ts",
|
|
53
|
+
"./work/sandbox": "./work/src/sandbox/index.ts",
|
|
54
|
+
"./work/sheets": "./work/src/sheets/index.ts",
|
|
55
|
+
"./work/skills": "./work/src/skills/index.ts",
|
|
56
|
+
"./work/tools": "./work/src/tools/index.ts"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"coding/src",
|
|
60
|
+
"!coding/src/**/__tests__",
|
|
61
|
+
"coding/README.md",
|
|
62
|
+
"web/src",
|
|
63
|
+
"!web/src/**/__tests__",
|
|
64
|
+
"web/skills",
|
|
65
|
+
"web/README.md",
|
|
66
|
+
"browser/src",
|
|
67
|
+
"!browser/src/**/__tests__",
|
|
68
|
+
"browser/skills",
|
|
69
|
+
"browser/README.md",
|
|
70
|
+
"research/src",
|
|
71
|
+
"!research/src/**/__tests__",
|
|
72
|
+
"research/skills",
|
|
73
|
+
"research/README.md",
|
|
74
|
+
"openapi/src",
|
|
75
|
+
"!openapi/src/**/__tests__",
|
|
76
|
+
"openapi/README.md",
|
|
77
|
+
"computer-use/src",
|
|
78
|
+
"!computer-use/src/**/__tests__",
|
|
79
|
+
"computer-use/skills",
|
|
80
|
+
"computer-use/README.md",
|
|
81
|
+
"work/src",
|
|
82
|
+
"!work/src/**/__tests__",
|
|
83
|
+
"work/docling",
|
|
84
|
+
"work/sandbox",
|
|
85
|
+
"work/vendor",
|
|
86
|
+
"work/vendor-lock.json",
|
|
87
|
+
"work/THIRD_PARTY_NOTICES",
|
|
88
|
+
"work/README.md",
|
|
89
|
+
"README.md",
|
|
90
|
+
"CHANGELOG.md",
|
|
91
|
+
"LICENSE"
|
|
92
|
+
],
|
|
93
|
+
"scripts": {
|
|
94
|
+
"test": "bun ../../scripts/with-build-lock.mjs --shared bun test --parallel=4 --timeout=0 coding/src web/src browser/src research/src openapi/src computer-use/src work/src",
|
|
95
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
96
|
+
"test:office": "PRISM_TEST_LIBREOFFICE=1 bun ../../scripts/with-build-lock.mjs --shared bun test --timeout=0 work/src/documents/__tests__/golden.test.ts",
|
|
97
|
+
"pack:dry-run": "bun pm pack --dry-run"
|
|
98
|
+
},
|
|
99
|
+
"dependencies": {
|
|
100
|
+
"diff": "^9.0.0",
|
|
101
|
+
"@mozilla/readability": "0.6.0",
|
|
102
|
+
"linkedom": "0.18.14",
|
|
103
|
+
"turndown": "7.2.4"
|
|
104
|
+
},
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"@arnilo/prism": ">=0.13.0 <1.0.0",
|
|
107
|
+
"@arnilo/prism-extensions": "^0.13.0",
|
|
108
|
+
"@office-open/docx": "0.14.5",
|
|
109
|
+
"@office-open/pptx": "0.14.5",
|
|
110
|
+
"@office-open/xlsx": "0.14.5",
|
|
111
|
+
"@office-open/xml": "0.14.5",
|
|
112
|
+
"ajv": "^8.17.1",
|
|
113
|
+
"fast-xml-parser": "5.11.1",
|
|
114
|
+
"e2b": "2.49.1",
|
|
115
|
+
"playwright-core": "1.63.0",
|
|
116
|
+
"@firecrawl/anydoc": "0.2.4",
|
|
117
|
+
"mammoth": "^1.8.0",
|
|
118
|
+
"pdf-parse": "^2.4.5"
|
|
119
|
+
},
|
|
120
|
+
"peerDependenciesMeta": {
|
|
121
|
+
"@office-open/docx": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"@office-open/pptx": {
|
|
125
|
+
"optional": true
|
|
126
|
+
},
|
|
127
|
+
"@office-open/xlsx": {
|
|
128
|
+
"optional": true
|
|
129
|
+
},
|
|
130
|
+
"@office-open/xml": {
|
|
131
|
+
"optional": true
|
|
132
|
+
},
|
|
133
|
+
"ajv": {
|
|
134
|
+
"optional": true
|
|
135
|
+
},
|
|
136
|
+
"fast-xml-parser": {
|
|
137
|
+
"optional": true
|
|
138
|
+
},
|
|
139
|
+
"e2b": {
|
|
140
|
+
"optional": true
|
|
141
|
+
},
|
|
142
|
+
"playwright-core": {
|
|
143
|
+
"optional": true
|
|
144
|
+
},
|
|
145
|
+
"@firecrawl/anydoc": {
|
|
146
|
+
"optional": true
|
|
147
|
+
},
|
|
148
|
+
"mammoth": {
|
|
149
|
+
"optional": true
|
|
150
|
+
},
|
|
151
|
+
"pdf-parse": {
|
|
152
|
+
"optional": true
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"devDependencies": {
|
|
156
|
+
"@types/diff": "^7.0.2",
|
|
157
|
+
"@types/node": "^22.20.0",
|
|
158
|
+
"typescript": "^7.0.2",
|
|
159
|
+
"@arnilo/prism-extensions": "0.13.0",
|
|
160
|
+
"@types/turndown": "5.0.6",
|
|
161
|
+
"playwright-core": "1.63.0",
|
|
162
|
+
"@firecrawl/anydoc": "0.2.4",
|
|
163
|
+
"mammoth": "^1.8.0",
|
|
164
|
+
"pdf-parse": "^2.4.5",
|
|
165
|
+
"@office-open/docx": "0.14.5",
|
|
166
|
+
"@office-open/pptx": "0.14.5",
|
|
167
|
+
"@office-open/xlsx": "0.14.5",
|
|
168
|
+
"@office-open/xml": "0.14.5",
|
|
169
|
+
"ajv": "^8.17.1",
|
|
170
|
+
"fast-xml-parser": "5.11.1",
|
|
171
|
+
"@arnilo/prism-hosts": "0.13.0"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @arnilo/prism-tools/research
|
|
2
|
+
|
|
3
|
+
Installing this package gives an agent four research skills, a per-session source ledger, a read-only `cite` tool, and a citation check at the end of a run.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
prism add @arnilo/prism-tools/research
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```jsonc
|
|
12
|
+
{
|
|
13
|
+
"packages": {
|
|
14
|
+
"@arnilo/prism-tools/research": {}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Every config field has a default. Set `maxRepairs` or `requireCitations` only when the defaults are wrong.
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
| Field | Type | Default | Description |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `sourceTools` | `string[]` | `web_fetch`, `web_search`, `web_extract`, `browser_observe`, `rag_search` | Tool names whose results are ledger sources. A name that is never registered is allowed and noted once. |
|
|
26
|
+
| `maxRepairs` | integer `0`–`3` | `1` | Extra model turns used to repair unresolved citations. `0` spends none. |
|
|
27
|
+
| `maxSources` | integer `1`–`5000` | `500` | Ledger size at which recording stops. |
|
|
28
|
+
| `requireCitations` | boolean | `false` | A report with no `[[cite:<id>]]` markers counts as unresolved. |
|
|
29
|
+
| `redactQuery` | `string[]` | `key`, `token`, `api_key`, `access_token`, `sig`, `signature` | Query parameter names stripped before a URL is stored. |
|
|
30
|
+
|
|
31
|
+
Unknown keys are rejected. `maxRepairs` above 3 and `maxSources` above 5000 are rejected.
|
|
32
|
+
|
|
33
|
+
## What it changes
|
|
34
|
+
|
|
35
|
+
- Tools: `cite` (`effects: []`). `cite({ id, quote? })` returns `[[cite:<id>]]` when `id` is in the ledger, or an error result `unknown_source` when it is not. `quote` is not stored.
|
|
36
|
+
- Skills: `research-scoping`, `source-triage`, `research-synthesis`, `research-report`, loaded from this package and progressive by default. The report skill tells the model to cite with markers from `cite`, and declares `requiresTools: cite`, so a request without that tool does not list it. Each description opens with when to use the skill (`scripts/package-skills-conformance.mjs` holds them to the package-skill contract in [Packages](../../../docs/packages.md#writing-a-package-skill)).
|
|
37
|
+
- Command: `research.verify` → `{ verdict, unresolved, ledgerSize }` for the given session. `verdict` is `pending` until a run ends, then `passed` or `failed`. With no session it returns `pending` and does not throw.
|
|
38
|
+
- Hooks: `tool.result` (transform, id `ledger`) and `run.end` (decide, id `citations`). A new source appends `ledger: S<n>` to the tool result. The transcript keeps `value` and drops text content when `value` is set, so the same line is also `value.ledger`.
|
|
39
|
+
- Events: `research.citations.unresolved` with `{ unresolved: string[] }` when the check fails after the repair bound.
|
|
40
|
+
- Session state: ledger entries `{ id, url | docId, title?, tool, toolCallId, fetchedAt }`. Ids are `S1`, `S2`, … and the same URL reuses its id. One package-state write per new source.
|
|
41
|
+
|
|
42
|
+
The ledger reads tool results by name. It does not import `tools-web`, `tools-browser`, or `memory-rag`.
|
|
43
|
+
|
|
44
|
+
## Capabilities
|
|
45
|
+
|
|
46
|
+
`session-state` — the ledger and the verdict live in per-session package state.
|
|
47
|
+
|
|
48
|
+
## Cost, security, and failure behavior
|
|
49
|
+
|
|
50
|
+
Each repair is one extra model turn, bounded by `maxRepairs` (default 1). `maxRepairs: 0` avoids it. The kernel also caps continuations (`limits.maxContinuations`, default 1). Set that ceiling at least as high as `maxRepairs`, or a repair request is dropped and the verdict stays `pending`.
|
|
51
|
+
|
|
52
|
+
`run.end` continues while repairs remain and a marker does not resolve. The first continue wins, so do not list another `run.end` package (such as `hooks-json`) on the same agent. After the bound, the verdict is `failed` and the package emits `research.citations.unresolved`. It does not throw.
|
|
53
|
+
|
|
54
|
+
A ledger at `maxSources` stops recording and writes one `warn` status note. A configured source tool that is not registered writes one `info` note. Neither throws.
|
|
55
|
+
|
|
56
|
+
Ledger entries store the URL, title, tool name, and ids only. Userinfo and the `redactQuery` parameters are stripped. Result bodies and tool arguments are not stored.
|
|
57
|
+
|
|
58
|
+
## Example
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { createAgent } from "@arnilo/prism";
|
|
62
|
+
import { mockProvider } from "@arnilo/prism/testing";
|
|
63
|
+
import toolsResearch from "@arnilo/prism-tools/research";
|
|
64
|
+
|
|
65
|
+
const agent = await createAgent({
|
|
66
|
+
model: { provider: "mock", model: "m" },
|
|
67
|
+
packages: [mockProvider(), toolsResearch({ maxRepairs: 0, requireCitations: true })],
|
|
68
|
+
});
|
|
69
|
+
const session = await agent.session({ id: "report", create: true });
|
|
70
|
+
await agent.commands.run("research.verify", {}, { session });
|
|
71
|
+
// → { verdict: "pending", unresolved: [], ledgerSize: 0 }
|
|
72
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: research-report
|
|
3
|
+
description: Use when writing the report. Every factual claim cites a ledger id with a marker from the cite tool.
|
|
4
|
+
metadata:
|
|
5
|
+
prism-requires-tools: cite
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Research report
|
|
9
|
+
|
|
10
|
+
1. Call `cite` with a ledger id. It returns `[[cite:<id>]]` when that id was fetched, and `unknown_source` otherwise.
|
|
11
|
+
2. Put that marker next to the claim. Do not invent a marker or an id.
|
|
12
|
+
3. A marker the ledger does not hold fails the citation check.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: research-scoping
|
|
3
|
+
description: Use before any fetch. Turns a research question into a bounded question, inclusion rules, and the sources worth fetching.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Research scoping
|
|
7
|
+
|
|
8
|
+
1. Restate the question in one sentence.
|
|
9
|
+
2. List what would count as a source and what to ignore.
|
|
10
|
+
3. Name the searches to run. Do not fetch yet.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: research-synthesis
|
|
3
|
+
description: Use after triage and before the report. Groups the kept sources into claims, each tied to ledger ids.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Research synthesis
|
|
7
|
+
|
|
8
|
+
1. One claim per cluster of ledger ids.
|
|
9
|
+
2. A claim with no ledger id is not ready to report.
|
|
10
|
+
3. Do not invent an id. Only ids printed as `ledger: S<n>` exist.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: source-triage
|
|
3
|
+
description: Use after ledger lines appear on tool results. Decides which fetched sources belong in the report.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Source triage
|
|
7
|
+
|
|
8
|
+
1. Read each `ledger: S<n>` line. That id is the only handle for the source.
|
|
9
|
+
2. Keep a source only when it bears on the scoped question.
|
|
10
|
+
3. Drop duplicates. The same URL keeps one id.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { UNTRUSTED_EXTERNAL_TRUST, type Message, type ToolResult } from "@arnilo/prism";
|
|
2
|
+
|
|
3
|
+
import type { LedgerEntry, ResearchState } from "./ledger.js";
|
|
4
|
+
|
|
5
|
+
const MARKER = /\[\[cite:([A-Za-z0-9_-]+)\]\]/g;
|
|
6
|
+
export const NO_CITATIONS = "<no-citations>";
|
|
7
|
+
|
|
8
|
+
export function lastAssistantText(history: readonly Message[]): string {
|
|
9
|
+
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
10
|
+
const message = history[i];
|
|
11
|
+
if (message?.role !== "assistant") continue;
|
|
12
|
+
return message.content.flatMap((part) => (part.type === "text" ? [part.text] : [])).join("");
|
|
13
|
+
}
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function citationIds(text: string): readonly string[] {
|
|
18
|
+
const ids: string[] = [];
|
|
19
|
+
for (const match of text.matchAll(MARKER)) {
|
|
20
|
+
const id = match[1];
|
|
21
|
+
if (id !== undefined && !ids.includes(id)) ids.push(id);
|
|
22
|
+
}
|
|
23
|
+
return ids;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function unresolvedIds(ids: readonly string[], entries: readonly LedgerEntry[], requireCitations: boolean): readonly string[] {
|
|
27
|
+
const known = new Set(entries.map((entry) => entry.id));
|
|
28
|
+
const missing = ids.filter((id) => !known.has(id));
|
|
29
|
+
if (missing.length === 0 && ids.length === 0 && requireCitations) return [NO_CITATIONS];
|
|
30
|
+
return missing;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function citationDecision(
|
|
34
|
+
state: ResearchState,
|
|
35
|
+
unresolved: readonly string[],
|
|
36
|
+
maxRepairs: number,
|
|
37
|
+
): { readonly state: ResearchState; readonly continueReason?: string } {
|
|
38
|
+
if (unresolved.length === 0) {
|
|
39
|
+
return { state: { ...state, verdict: "passed", unresolved: [] } };
|
|
40
|
+
}
|
|
41
|
+
if (state.repairs < maxRepairs) {
|
|
42
|
+
return {
|
|
43
|
+
state: { ...state, repairs: state.repairs + 1, unresolved },
|
|
44
|
+
continueReason: `Unresolved citations: ${unresolved.join(", ")}. Cite only ledger ids from ledger: S<n> lines, using cite.`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return { state: { ...state, verdict: "failed", unresolved } };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function withLedgerLine(result: ToolResult, line: string): ToolResult {
|
|
51
|
+
const note = { type: "text" as const, text: line };
|
|
52
|
+
// Untrusted results reach the model as their text content (the kernel envelope), so the line rides
|
|
53
|
+
// the text. Trusted results still drop text when `value` is set, so they keep the copy in `value`.
|
|
54
|
+
const untrusted = result.metadata?.trust === UNTRUSTED_EXTERNAL_TRUST;
|
|
55
|
+
const value =
|
|
56
|
+
!untrusted && typeof result.value === "object" && result.value !== null && !Array.isArray(result.value)
|
|
57
|
+
? { ...result.value, ledger: line }
|
|
58
|
+
: result.value;
|
|
59
|
+
return {
|
|
60
|
+
toolCallId: result.toolCallId,
|
|
61
|
+
name: result.name,
|
|
62
|
+
content: [...(result.content ?? []), note],
|
|
63
|
+
...(value === undefined ? {} : { value }),
|
|
64
|
+
...(result.error === undefined ? {} : { error: result.error }),
|
|
65
|
+
...(result.metadata === undefined ? {} : { metadata: result.metadata }),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function citeMarker(id: string): string {
|
|
70
|
+
return `[[cite:${id}]]`;
|
|
71
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { JsonSchema } from "@arnilo/prism";
|
|
2
|
+
|
|
3
|
+
/** Tools whose results are ledger sources. A name that is never registered is noted, not rejected. */
|
|
4
|
+
export const DEFAULT_SOURCE_TOOLS = ["web_fetch", "web_search", "web_extract", "browser_observe", "rag_search"] as const;
|
|
5
|
+
|
|
6
|
+
/** Query parameter names stripped before a URL is stored. */
|
|
7
|
+
export const DEFAULT_REDACT_QUERY = ["key", "token", "api_key", "access_token", "sig", "signature"] as const;
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_MAX_REPAIRS = 1;
|
|
10
|
+
export const HARD_MAX_REPAIRS = 3;
|
|
11
|
+
export const DEFAULT_MAX_SOURCES = 500;
|
|
12
|
+
export const HARD_MAX_SOURCES = 5_000;
|
|
13
|
+
|
|
14
|
+
export interface ToolsResearchConfig {
|
|
15
|
+
readonly sourceTools?: readonly string[];
|
|
16
|
+
/** Extra model turns spent repairing unresolved citations. `0` spends none. */
|
|
17
|
+
readonly maxRepairs?: number;
|
|
18
|
+
/** Ledger size at which recording stops. */
|
|
19
|
+
readonly maxSources?: number;
|
|
20
|
+
/** A report with no `[[cite:<id>]]` markers counts as unresolved. Default false. */
|
|
21
|
+
readonly requireCitations?: boolean;
|
|
22
|
+
readonly redactQuery?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const stringList = (maxItems: number): JsonSchema => ({
|
|
26
|
+
type: "array",
|
|
27
|
+
maxItems,
|
|
28
|
+
items: { type: "string", minLength: 1, maxLength: 64 },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const toolsResearchConfigSchema: JsonSchema = {
|
|
32
|
+
type: "object",
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
properties: {
|
|
35
|
+
sourceTools: { ...stringList(32), default: [...DEFAULT_SOURCE_TOOLS] },
|
|
36
|
+
maxRepairs: { type: "integer", minimum: 0, maximum: HARD_MAX_REPAIRS, default: DEFAULT_MAX_REPAIRS },
|
|
37
|
+
maxSources: { type: "integer", minimum: 1, maximum: HARD_MAX_SOURCES, default: DEFAULT_MAX_SOURCES },
|
|
38
|
+
requireCitations: { type: "boolean", default: false },
|
|
39
|
+
redactQuery: { ...stringList(32), default: [...DEFAULT_REDACT_QUERY] },
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@arnilo/prism-tools/research` — research skills, a source ledger, and a citation check.
|
|
3
|
+
*
|
|
4
|
+
* `tool.result` records sources from the configured tool names. `cite` returns a `[[cite:<id>]]`
|
|
5
|
+
* marker for a ledger id. `run.end` continues while repairs remain, then records a failed verdict.
|
|
6
|
+
* `maxRepairs: 0` spends no extra model turn.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { definePackage, type JsonValue, type PackageInstance, type SessionContext, type ToolResult } from "@arnilo/prism";
|
|
11
|
+
import manifest from "../../package.json" with { type: "json" };
|
|
12
|
+
|
|
13
|
+
import { citationDecision, citationIds, citeMarker, lastAssistantText, unresolvedIds, withLedgerLine } from "./check.js";
|
|
14
|
+
import { type ToolsResearchConfig, toolsResearchConfigSchema } from "./config.js";
|
|
15
|
+
import { EMPTY_STATE, ledgerLine, type ResearchState, recordSources, sourcesIn } from "./ledger.js";
|
|
16
|
+
|
|
17
|
+
const PACKAGE = "@arnilo/prism-tools/research";
|
|
18
|
+
|
|
19
|
+
interface Flags {
|
|
20
|
+
readonly missingNoted: boolean;
|
|
21
|
+
readonly capNoted: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const EMPTY_FLAGS: Flags = { missingNoted: false, capNoted: false };
|
|
25
|
+
|
|
26
|
+
const definition = definePackage<ToolsResearchConfig>({
|
|
27
|
+
name: PACKAGE,
|
|
28
|
+
version: manifest.version,
|
|
29
|
+
description: "Research skills, a per-session source ledger, cite, and a bounded citation check.",
|
|
30
|
+
requires: { api: 1 },
|
|
31
|
+
capabilities: ["session-state"],
|
|
32
|
+
config: toolsResearchConfigSchema,
|
|
33
|
+
setup(prism) {
|
|
34
|
+
// Session state stores JSON. ResearchState is that object; it has no index signature.
|
|
35
|
+
const research = prism.state.session("research", EMPTY_STATE as unknown as JsonValue);
|
|
36
|
+
const flags = prism.state.agent("flags", EMPTY_FLAGS);
|
|
37
|
+
const sourceTools = new Set(prism.config.sourceTools ?? []);
|
|
38
|
+
|
|
39
|
+
const noteMissing = (): void => {
|
|
40
|
+
const current = flags.get();
|
|
41
|
+
if (current.missingNoted) return;
|
|
42
|
+
const registered = new Set(prism.tools.list().map((tool) => tool.name));
|
|
43
|
+
const missing = [...sourceTools].filter((name) => !registered.has(name));
|
|
44
|
+
if (missing.length === 0) return;
|
|
45
|
+
prism.status.note("info", `source tools not registered: ${missing.join(", ")}`);
|
|
46
|
+
flags.set({ ...flags.get(), missingNoted: true });
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const read = (session: SessionContext): ResearchState => (research.get(session) as unknown as ResearchState | undefined) ?? EMPTY_STATE;
|
|
50
|
+
|
|
51
|
+
prism.hooks.on(
|
|
52
|
+
"tool.result",
|
|
53
|
+
(result, context) => {
|
|
54
|
+
noteMissing();
|
|
55
|
+
if (!sourceTools.has(result.name) || result.error !== undefined || context.session === undefined) return undefined;
|
|
56
|
+
const before = read(context.session);
|
|
57
|
+
const recorded = recordSources(before, sourcesIn(result.name, result.value, prism.config.redactQuery ?? []), {
|
|
58
|
+
tool: result.name,
|
|
59
|
+
toolCallId: result.toolCallId,
|
|
60
|
+
fetchedAt: new Date().toISOString(),
|
|
61
|
+
maxSources: prism.config.maxSources ?? 500,
|
|
62
|
+
});
|
|
63
|
+
if (recorded.cappedNow && !flags.get().capNoted) {
|
|
64
|
+
prism.status.note("warn", `ledger reached maxSources (${prism.config.maxSources}); further sources are not recorded`);
|
|
65
|
+
flags.set({ ...flags.get(), capNoted: true });
|
|
66
|
+
}
|
|
67
|
+
if (recorded.state === before) return undefined;
|
|
68
|
+
research.set(context.session, recorded.state as unknown as JsonValue);
|
|
69
|
+
return recorded.added.length === 0 ? undefined : withLedgerLine(result, ledgerLine(recorded.added));
|
|
70
|
+
},
|
|
71
|
+
{ id: "ledger" },
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
prism.hooks.on(
|
|
75
|
+
"run.end",
|
|
76
|
+
(payload, context) => {
|
|
77
|
+
noteMissing();
|
|
78
|
+
if (context.session === undefined) return undefined;
|
|
79
|
+
const current = read(context.session);
|
|
80
|
+
const decision = citationDecision(
|
|
81
|
+
current,
|
|
82
|
+
unresolvedIds(citationIds(lastAssistantText(payload.history)), current.entries, prism.config.requireCitations === true),
|
|
83
|
+
prism.config.maxRepairs ?? 1,
|
|
84
|
+
);
|
|
85
|
+
research.set(context.session, decision.state as unknown as JsonValue);
|
|
86
|
+
if (decision.state.verdict === "failed") {
|
|
87
|
+
context.emit("research.citations.unresolved", { unresolved: [...decision.state.unresolved] });
|
|
88
|
+
}
|
|
89
|
+
return decision.continueReason === undefined ? undefined : { continue: { reason: decision.continueReason } };
|
|
90
|
+
},
|
|
91
|
+
{ id: "citations" },
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
prism.tools.register({
|
|
95
|
+
name: "cite",
|
|
96
|
+
description:
|
|
97
|
+
"Return a [[cite:<id>]] marker for a source already in this session's ledger. Fails with unknown_source when the id was not fetched.",
|
|
98
|
+
effects: [],
|
|
99
|
+
parameters: {
|
|
100
|
+
type: "object",
|
|
101
|
+
additionalProperties: false,
|
|
102
|
+
properties: {
|
|
103
|
+
id: { type: "string", minLength: 1, maxLength: 64 },
|
|
104
|
+
quote: { type: "string", maxLength: 500 },
|
|
105
|
+
},
|
|
106
|
+
required: ["id"],
|
|
107
|
+
},
|
|
108
|
+
execute(args, context): ToolResult {
|
|
109
|
+
const id = typeof args.id === "string" ? args.id : "";
|
|
110
|
+
const known = context.session !== undefined && read(context.session).entries.some((entry) => entry.id === id);
|
|
111
|
+
if (!known) {
|
|
112
|
+
return {
|
|
113
|
+
toolCallId: context.toolCallId,
|
|
114
|
+
name: "cite",
|
|
115
|
+
error: { code: "unknown_source", message: `unknown source ${id}` },
|
|
116
|
+
content: [{ type: "text", text: `unknown_source: ${id}` }],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
toolCallId: context.toolCallId,
|
|
121
|
+
name: "cite",
|
|
122
|
+
value: { id },
|
|
123
|
+
content: [{ type: "text", text: citeMarker(id) }],
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
prism.commands.register({
|
|
129
|
+
name: "research.verify",
|
|
130
|
+
description: "Return the citation verdict, unresolved ids, and ledger size for a session.",
|
|
131
|
+
run(_args, context) {
|
|
132
|
+
if (context.session === undefined) return { verdict: "pending", unresolved: [], ledgerSize: 0 };
|
|
133
|
+
const state = read(context.session);
|
|
134
|
+
return { verdict: state.verdict, unresolved: [...state.unresolved], ledgerSize: state.entries.length };
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
prism.skills.addDir(fileURLToPath(new URL("../skills", import.meta.url)));
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export default definition;
|
|
143
|
+
|
|
144
|
+
/** The package with config baked in, for `packages: [toolsResearch({ maxRepairs: 0 })]`. */
|
|
145
|
+
export function toolsResearch(config: ToolsResearchConfig = {}): PackageInstance {
|
|
146
|
+
return definition(config);
|
|
147
|
+
}
|