@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,465 @@
|
|
|
1
|
+
import { type JsonObject } from "@arnilo/prism";
|
|
2
|
+
import { type ArtifactBodyStore } from "@arnilo/prism/artifacts";
|
|
3
|
+
import type { CheckpointStore } from "@arnilo/prism-extensions/workflows";
|
|
4
|
+
import { assertSafeArgv, createCliRunner, parseCliJson, parseCliNdjson } from "./cli.js";
|
|
5
|
+
import { createCheckpointWorkDraftStore, createMemoryWorkDraftStore } from "./drafts.js";
|
|
6
|
+
import { WorkToolError } from "./errors.js";
|
|
7
|
+
import { type AgentIdentity, assertIdentityActive } from "./identity.js";
|
|
8
|
+
import { resolveWorkLimits } from "./limits.js";
|
|
9
|
+
import type { GoogleWorkspaceAdapter, GoogleWorkspaceOp, WorkCliRunner, WorkDraftStore, WorkLimits, WorkTokenProvider } from "./types.js";
|
|
10
|
+
/** Default ops enabled without Docs/Sheets/Slides capability gates. */
|
|
11
|
+
export const DEFAULT_GWS_OPS: readonly GoogleWorkspaceOp[] = [
|
|
12
|
+
"version",
|
|
13
|
+
"mail.list",
|
|
14
|
+
"mail.get",
|
|
15
|
+
"mail.send",
|
|
16
|
+
"calendar.list",
|
|
17
|
+
"calendar.add",
|
|
18
|
+
"file.list",
|
|
19
|
+
"file.add",
|
|
20
|
+
"file.share",
|
|
21
|
+
"task.list",
|
|
22
|
+
"task.add",
|
|
23
|
+
"task.complete",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
/** Ops excluded from DEFAULT_GWS_OPS; host must pass them in allowedOps. */
|
|
27
|
+
export const GATED_GWS_OPS: ReadonlySet<GoogleWorkspaceOp> = new Set([
|
|
28
|
+
"docs.create",
|
|
29
|
+
"docs.update",
|
|
30
|
+
"sheets.create",
|
|
31
|
+
"sheets.update",
|
|
32
|
+
"slides.create",
|
|
33
|
+
"slides.update",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
function reqString(args: JsonObject, key: string): string {
|
|
37
|
+
const value = args[key];
|
|
38
|
+
if (typeof value !== "string" || !value) throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be a non-empty string`);
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function optString(args: JsonObject, key: string): string | undefined {
|
|
43
|
+
const value = args[key];
|
|
44
|
+
if (value === undefined) return undefined;
|
|
45
|
+
if (typeof value !== "string" || !value) throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be a non-empty string`);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function paramsJson(value: JsonObject): string {
|
|
50
|
+
return JSON.stringify(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function reqText(args: JsonObject, key: string): string {
|
|
54
|
+
const value = args[key];
|
|
55
|
+
if (typeof value !== "string") throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be a string`);
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function optObject(args: JsonObject, key: string): JsonObject | undefined {
|
|
60
|
+
const value = args[key];
|
|
61
|
+
if (value === undefined) return undefined;
|
|
62
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
63
|
+
throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be an object`);
|
|
64
|
+
}
|
|
65
|
+
return value as JsonObject;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function assertKeys(args: JsonObject, allowed: readonly string[]): void {
|
|
69
|
+
for (const key of Object.keys(args)) {
|
|
70
|
+
if (!allowed.includes(key)) throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} is not allowed`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function positiveInteger(args: JsonObject, key: string): number {
|
|
75
|
+
const value = args[key];
|
|
76
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
|
|
77
|
+
throw new WorkToolError("ERR_PRISM_WORK_INPUT", `${key} must be an integer >= 1`);
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function stringMatrix(args: JsonObject): string[][] {
|
|
83
|
+
const value = args.values;
|
|
84
|
+
if (!Array.isArray(value)) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "values must be an array of string arrays");
|
|
85
|
+
return value.map((row) => {
|
|
86
|
+
if (!Array.isArray(row) || row.some((cell) => typeof cell !== "string")) {
|
|
87
|
+
throw new WorkToolError("ERR_PRISM_WORK_INPUT", "values must be an array of string arrays");
|
|
88
|
+
}
|
|
89
|
+
return row as string[];
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Maps fixed tool inputs to Google API batch bodies; never accepts free-form requests. */
|
|
94
|
+
export function googleWorkspaceUpdate(
|
|
95
|
+
op: "docs.update" | "sheets.update" | "slides.update",
|
|
96
|
+
args: JsonObject,
|
|
97
|
+
): { readonly resourceId: string; readonly body: JsonObject } {
|
|
98
|
+
switch (op) {
|
|
99
|
+
case "docs.update": {
|
|
100
|
+
assertKeys(args, ["documentId", "replaceAllText", "insertText"]);
|
|
101
|
+
const replaceAllText = optObject(args, "replaceAllText");
|
|
102
|
+
const insertText = optObject(args, "insertText");
|
|
103
|
+
if (!replaceAllText && !insertText) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "provide replaceAllText or insertText");
|
|
104
|
+
const requests: JsonObject[] = [];
|
|
105
|
+
if (replaceAllText) {
|
|
106
|
+
assertKeys(replaceAllText, ["containsText", "replaceText"]);
|
|
107
|
+
requests.push({
|
|
108
|
+
replaceAllText: {
|
|
109
|
+
containsText: { text: reqString(replaceAllText, "containsText") },
|
|
110
|
+
replaceText: reqText(replaceAllText, "replaceText"),
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (insertText) {
|
|
115
|
+
assertKeys(insertText, ["locationIndex", "text"]);
|
|
116
|
+
requests.push({
|
|
117
|
+
insertText: {
|
|
118
|
+
location: { index: positiveInteger(insertText, "locationIndex") },
|
|
119
|
+
text: reqText(insertText, "text"),
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return { resourceId: reqString(args, "documentId"), body: { requests } };
|
|
124
|
+
}
|
|
125
|
+
case "sheets.update":
|
|
126
|
+
assertKeys(args, ["spreadsheetId", "range", "values"]);
|
|
127
|
+
return { resourceId: reqString(args, "spreadsheetId"), body: { values: stringMatrix(args) } };
|
|
128
|
+
case "slides.update": {
|
|
129
|
+
assertKeys(args, ["presentationId", "insertText"]);
|
|
130
|
+
const insertText = optObject(args, "insertText");
|
|
131
|
+
if (!insertText) throw new WorkToolError("ERR_PRISM_WORK_INPUT", "insertText must be an object");
|
|
132
|
+
assertKeys(insertText, ["objectId", "text"]);
|
|
133
|
+
return {
|
|
134
|
+
resourceId: reqString(args, "presentationId"),
|
|
135
|
+
body: { requests: [{ insertText: { objectId: reqString(insertText, "objectId"), text: reqText(insertText, "text") } }] },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Hard-coded argv templates for @googleworkspace/cli (`gws`), verified 2026-07-24 docs:
|
|
143
|
+
* - gmail users messages list/get; gmail +send
|
|
144
|
+
* - calendar events list; calendar events insert
|
|
145
|
+
* - drive files list/create; drive permissions create (domain only)
|
|
146
|
+
* - tasks tasks list/insert/patch
|
|
147
|
+
* - docs/sheets/slides create (capability-gated)
|
|
148
|
+
* Never expose Discovery free-form (`schema`) or `auth`/`login`/`setup`.
|
|
149
|
+
*/
|
|
150
|
+
export function buildGoogleWorkspaceArgv(op: GoogleWorkspaceOp, args: JsonObject): string[] {
|
|
151
|
+
switch (op) {
|
|
152
|
+
case "version":
|
|
153
|
+
return ["--version"];
|
|
154
|
+
case "mail.list": {
|
|
155
|
+
const q = optString(args, "q");
|
|
156
|
+
const maxResults = optString(args, "maxResults");
|
|
157
|
+
const params: JsonObject = {
|
|
158
|
+
userId: optString(args, "userId") ?? "me",
|
|
159
|
+
...(q ? { q } : {}),
|
|
160
|
+
...(maxResults ? { maxResults: Number(maxResults) } : {}),
|
|
161
|
+
};
|
|
162
|
+
return ["gmail", "users", "messages", "list", "--params", paramsJson(params), "--fields", "messages(id,threadId,snippet)"];
|
|
163
|
+
}
|
|
164
|
+
case "mail.get":
|
|
165
|
+
return [
|
|
166
|
+
"gmail",
|
|
167
|
+
"users",
|
|
168
|
+
"messages",
|
|
169
|
+
"get",
|
|
170
|
+
"--params",
|
|
171
|
+
paramsJson({ userId: optString(args, "userId") ?? "me", id: reqString(args, "id") }),
|
|
172
|
+
"--fields",
|
|
173
|
+
"id,threadId,snippet,payload/headers,labelIds",
|
|
174
|
+
];
|
|
175
|
+
case "mail.send": {
|
|
176
|
+
// Convenience helper avoids model-controlled raw MIME/base64.
|
|
177
|
+
const argv = [
|
|
178
|
+
"gmail",
|
|
179
|
+
"+send",
|
|
180
|
+
"--to",
|
|
181
|
+
reqString(args, "to"),
|
|
182
|
+
"--subject",
|
|
183
|
+
reqString(args, "subject"),
|
|
184
|
+
"--body",
|
|
185
|
+
reqString(args, "body"),
|
|
186
|
+
];
|
|
187
|
+
const cc = optString(args, "cc");
|
|
188
|
+
const bcc = optString(args, "bcc");
|
|
189
|
+
const from = optString(args, "from");
|
|
190
|
+
if (cc) argv.push("--cc", cc);
|
|
191
|
+
if (bcc) argv.push("--bcc", bcc);
|
|
192
|
+
if (from) argv.push("--from", from);
|
|
193
|
+
return argv;
|
|
194
|
+
}
|
|
195
|
+
case "calendar.list": {
|
|
196
|
+
const timeMin = optString(args, "timeMin");
|
|
197
|
+
const timeMax = optString(args, "timeMax");
|
|
198
|
+
const maxResults = optString(args, "maxResults");
|
|
199
|
+
const params: JsonObject = {
|
|
200
|
+
calendarId: optString(args, "calendarId") ?? "primary",
|
|
201
|
+
...(timeMin ? { timeMin } : {}),
|
|
202
|
+
...(timeMax ? { timeMax } : {}),
|
|
203
|
+
...(maxResults ? { maxResults: Number(maxResults) } : {}),
|
|
204
|
+
};
|
|
205
|
+
return ["calendar", "events", "list", "--params", paramsJson(params), "--fields", "items(id,summary,start,end,etag)"];
|
|
206
|
+
}
|
|
207
|
+
case "calendar.add": {
|
|
208
|
+
const calendarId = optString(args, "calendarId") ?? "primary";
|
|
209
|
+
const body = {
|
|
210
|
+
summary: reqString(args, "summary"),
|
|
211
|
+
start: { dateTime: reqString(args, "start") },
|
|
212
|
+
end: { dateTime: reqString(args, "end") },
|
|
213
|
+
};
|
|
214
|
+
return ["calendar", "events", "insert", "--params", paramsJson({ calendarId }), "--json", JSON.stringify(body)];
|
|
215
|
+
}
|
|
216
|
+
case "file.list": {
|
|
217
|
+
const q = optString(args, "q");
|
|
218
|
+
const pageSize = optString(args, "pageSize");
|
|
219
|
+
const params: JsonObject = {
|
|
220
|
+
pageSize: pageSize ? Number(pageSize) : 10,
|
|
221
|
+
...(q ? { q } : {}),
|
|
222
|
+
};
|
|
223
|
+
const argv = ["drive", "files", "list", "--params", paramsJson(params), "--fields", "files(id,name,mimeType,size)"];
|
|
224
|
+
if (args.pageAll === true || args.pageAll === "true") argv.push("--page-all");
|
|
225
|
+
return argv;
|
|
226
|
+
}
|
|
227
|
+
case "file.get":
|
|
228
|
+
throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", "file.get requires the Google Workspace HTTP adapter");
|
|
229
|
+
case "file.add": {
|
|
230
|
+
const parentId = optString(args, "parentId");
|
|
231
|
+
const meta = {
|
|
232
|
+
name: reqString(args, "name"),
|
|
233
|
+
...(parentId ? { parents: [parentId] } : {}),
|
|
234
|
+
};
|
|
235
|
+
return ["drive", "files", "create", "--json", JSON.stringify(meta), "--upload", reqString(args, "filePath")];
|
|
236
|
+
}
|
|
237
|
+
case "file.share": {
|
|
238
|
+
const type = reqString(args, "type");
|
|
239
|
+
if (type === "anyone")
|
|
240
|
+
throw new WorkToolError("ERR_PRISM_WORK_POLICY", "Anonymous share denied; host must allow explicitly via policy override");
|
|
241
|
+
if (type !== "domain" && type !== "user") throw new WorkToolError("ERR_PRISM_WORK_INPUT", "type must be domain or user");
|
|
242
|
+
const role = optString(args, "role") ?? "reader";
|
|
243
|
+
if (role !== "reader" && role !== "writer" && role !== "commenter") {
|
|
244
|
+
throw new WorkToolError("ERR_PRISM_WORK_INPUT", "role must be reader, writer, or commenter");
|
|
245
|
+
}
|
|
246
|
+
const body: Record<string, string> = { role, type };
|
|
247
|
+
if (type === "domain") body.domain = reqString(args, "domain");
|
|
248
|
+
else body.emailAddress = reqString(args, "emailAddress");
|
|
249
|
+
return [
|
|
250
|
+
"drive",
|
|
251
|
+
"permissions",
|
|
252
|
+
"create",
|
|
253
|
+
"--params",
|
|
254
|
+
paramsJson({ fileId: reqString(args, "fileId") }),
|
|
255
|
+
"--json",
|
|
256
|
+
JSON.stringify(body),
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
case "task.list":
|
|
260
|
+
return ["tasks", "tasks", "list", "--params", paramsJson({ tasklist: optString(args, "tasklist") ?? "@default" })];
|
|
261
|
+
case "task.add":
|
|
262
|
+
return [
|
|
263
|
+
"tasks",
|
|
264
|
+
"tasks",
|
|
265
|
+
"insert",
|
|
266
|
+
"--params",
|
|
267
|
+
paramsJson({ tasklist: optString(args, "tasklist") ?? "@default" }),
|
|
268
|
+
"--json",
|
|
269
|
+
paramsJson({ title: reqString(args, "title") }),
|
|
270
|
+
];
|
|
271
|
+
case "task.complete":
|
|
272
|
+
return [
|
|
273
|
+
"tasks",
|
|
274
|
+
"tasks",
|
|
275
|
+
"patch",
|
|
276
|
+
"--params",
|
|
277
|
+
paramsJson({
|
|
278
|
+
tasklist: optString(args, "tasklist") ?? "@default",
|
|
279
|
+
task: reqString(args, "id"),
|
|
280
|
+
}),
|
|
281
|
+
"--json",
|
|
282
|
+
paramsJson({ status: "completed" }),
|
|
283
|
+
];
|
|
284
|
+
case "docs.create":
|
|
285
|
+
return ["docs", "documents", "create", "--json", paramsJson({ title: reqString(args, "title") })];
|
|
286
|
+
case "docs.update": {
|
|
287
|
+
const update = googleWorkspaceUpdate(op, args);
|
|
288
|
+
return [
|
|
289
|
+
"docs",
|
|
290
|
+
"documents",
|
|
291
|
+
"batchUpdate",
|
|
292
|
+
"--params",
|
|
293
|
+
paramsJson({ documentId: update.resourceId }),
|
|
294
|
+
"--json",
|
|
295
|
+
paramsJson(update.body),
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
case "sheets.create":
|
|
299
|
+
return ["sheets", "spreadsheets", "create", "--json", paramsJson({ properties: { title: reqString(args, "title") } })];
|
|
300
|
+
case "sheets.update": {
|
|
301
|
+
const update = googleWorkspaceUpdate(op, args);
|
|
302
|
+
return [
|
|
303
|
+
"sheets",
|
|
304
|
+
"spreadsheets",
|
|
305
|
+
"values",
|
|
306
|
+
"update",
|
|
307
|
+
"--params",
|
|
308
|
+
paramsJson({ spreadsheetId: update.resourceId, range: reqString(args, "range"), valueInputOption: "RAW" }),
|
|
309
|
+
"--json",
|
|
310
|
+
paramsJson(update.body),
|
|
311
|
+
];
|
|
312
|
+
}
|
|
313
|
+
case "slides.create":
|
|
314
|
+
return ["slides", "presentations", "create", "--json", paramsJson({ title: reqString(args, "title") })];
|
|
315
|
+
case "slides.update": {
|
|
316
|
+
const update = googleWorkspaceUpdate(op, args);
|
|
317
|
+
return [
|
|
318
|
+
"slides",
|
|
319
|
+
"presentations",
|
|
320
|
+
"batchUpdate",
|
|
321
|
+
"--params",
|
|
322
|
+
paramsJson({ presentationId: update.resourceId }),
|
|
323
|
+
"--json",
|
|
324
|
+
paramsJson(update.body),
|
|
325
|
+
];
|
|
326
|
+
}
|
|
327
|
+
default: {
|
|
328
|
+
const _exhaustive: never = op;
|
|
329
|
+
throw new WorkToolError("ERR_PRISM_WORK_OP", `Unknown op ${_exhaustive}`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface GoogleWorkspaceCliAdapterOptions {
|
|
335
|
+
readonly binary: string;
|
|
336
|
+
readonly identity: AgentIdentity;
|
|
337
|
+
readonly configDir: string;
|
|
338
|
+
readonly allowedOps?: readonly GoogleWorkspaceOp[];
|
|
339
|
+
readonly limits?: WorkLimits;
|
|
340
|
+
readonly runner?: WorkCliRunner;
|
|
341
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
342
|
+
readonly minVersion?: string;
|
|
343
|
+
/** Late-bound per-identity token source; undefined token fails the call closed. */
|
|
344
|
+
readonly tokenProvider?: WorkTokenProvider;
|
|
345
|
+
readonly draftStore?: WorkDraftStore;
|
|
346
|
+
readonly checkpoints?: CheckpointStore;
|
|
347
|
+
readonly bodies?: ArtifactBodyStore;
|
|
348
|
+
readonly ephemeralDrafts?: boolean;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function createGoogleWorkspaceCliAdapter(options: GoogleWorkspaceCliAdapterOptions): GoogleWorkspaceAdapter {
|
|
352
|
+
assertIdentityActive(options.identity);
|
|
353
|
+
const allowedOps = new Set(options.allowedOps ?? DEFAULT_GWS_OPS);
|
|
354
|
+
if (allowedOps.has("file.get"))
|
|
355
|
+
throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", "file.get requires the Google Workspace HTTP adapter");
|
|
356
|
+
const limits = resolveWorkLimits(options.limits);
|
|
357
|
+
const runner =
|
|
358
|
+
options.runner ??
|
|
359
|
+
createCliRunner({
|
|
360
|
+
binary: options.binary,
|
|
361
|
+
configDir: options.configDir,
|
|
362
|
+
limits: options.limits,
|
|
363
|
+
env: options.env,
|
|
364
|
+
});
|
|
365
|
+
const draftStore: WorkDraftStore =
|
|
366
|
+
options.draftStore ??
|
|
367
|
+
(options.checkpoints
|
|
368
|
+
? createCheckpointWorkDraftStore({
|
|
369
|
+
checkpoints: options.checkpoints,
|
|
370
|
+
bodies: options.bodies,
|
|
371
|
+
limits: options.limits,
|
|
372
|
+
})
|
|
373
|
+
: createMemoryWorkDraftStore({ ephemeral: options.ephemeralDrafts ?? true }));
|
|
374
|
+
let readyVersion: string | undefined;
|
|
375
|
+
|
|
376
|
+
const assertAllowed = (op: GoogleWorkspaceOp) => {
|
|
377
|
+
if (!allowedOps.has(op)) throw new WorkToolError("ERR_PRISM_WORK_CAPABILITY", `Operation ${op} not allowed for this identity`);
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
// Resolve the per-identity token env; a configured provider returning undefined means the
|
|
381
|
+
// credential is missing/expired/revoked, so the call fails closed before any side effect.
|
|
382
|
+
const tokenEnv = async (signal?: AbortSignal): Promise<Readonly<Record<string, string>> | undefined> => {
|
|
383
|
+
if (!options.tokenProvider) return undefined;
|
|
384
|
+
const envVars = await options.tokenProvider.tokenEnv(options.identity, signal);
|
|
385
|
+
if (!envVars) throw new WorkToolError("ERR_PRISM_WORK_CREDENTIAL", "Connector credential unavailable, expired, or revoked");
|
|
386
|
+
return envVars;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
provider: "google-workspace",
|
|
391
|
+
identity: options.identity,
|
|
392
|
+
allowedOps,
|
|
393
|
+
draftStore,
|
|
394
|
+
async ensureReady(signal) {
|
|
395
|
+
if (readyVersion) return readyVersion;
|
|
396
|
+
assertAllowed("version");
|
|
397
|
+
const argv = buildGoogleWorkspaceArgv("version", {});
|
|
398
|
+
assertSafeArgv(argv);
|
|
399
|
+
const result = await runner.exec(argv, { signal, env: await tokenEnv(signal) });
|
|
400
|
+
if (result.exitCode !== 0) throw new WorkToolError("ERR_PRISM_WORK_CLI", `gws version failed: ${result.stderr.slice(0, 200)}`);
|
|
401
|
+
const version = result.stdout.trim() || String(parseCliJson(result.stdout, limits) ?? "");
|
|
402
|
+
if (options.minVersion && version.replace(/^v/, "") < options.minVersion.replace(/^v/, "")) {
|
|
403
|
+
throw new WorkToolError("ERR_PRISM_WORK_VERSION", `CLI version ${version} below required ${options.minVersion}`);
|
|
404
|
+
}
|
|
405
|
+
readyVersion = version;
|
|
406
|
+
return version;
|
|
407
|
+
},
|
|
408
|
+
async runOp(op, args, signal) {
|
|
409
|
+
assertAllowed(op);
|
|
410
|
+
await this.ensureReady(signal);
|
|
411
|
+
const argv = buildGoogleWorkspaceArgv(op, args);
|
|
412
|
+
assertSafeArgv(argv);
|
|
413
|
+
const body = typeof args.body === "string" ? args.body : "";
|
|
414
|
+
if (Buffer.byteLength(body) > limits.maxRequestBytes) {
|
|
415
|
+
throw new WorkToolError("ERR_PRISM_WORK_LIMIT", "Request body exceeds byte limit");
|
|
416
|
+
}
|
|
417
|
+
const result = await runner.exec(argv, { signal, env: await tokenEnv(signal) });
|
|
418
|
+
if (result.exitCode !== 0) {
|
|
419
|
+
throw new WorkToolError("ERR_PRISM_WORK_CLI", `gws ${op} failed (exit ${result.exitCode})`);
|
|
420
|
+
}
|
|
421
|
+
if (argv.includes("--page-all")) {
|
|
422
|
+
return parseCliNdjson(result.stdout, limits);
|
|
423
|
+
}
|
|
424
|
+
return parseCliJson(result.stdout, limits);
|
|
425
|
+
},
|
|
426
|
+
createDraft(op, payload, draftOpts) {
|
|
427
|
+
assertAllowed(op);
|
|
428
|
+
return draftStore.createDraft({
|
|
429
|
+
draftId: draftOpts?.draftId,
|
|
430
|
+
provider: "google-workspace",
|
|
431
|
+
op,
|
|
432
|
+
identity: options.identity,
|
|
433
|
+
payload,
|
|
434
|
+
policyRevision: draftOpts?.policyRevision,
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
getDraft(draftId) {
|
|
438
|
+
return draftStore.getDraft({ draftId, identity: options.identity, provider: "google-workspace" });
|
|
439
|
+
},
|
|
440
|
+
updateDraft(draftId, payload, draftOpts) {
|
|
441
|
+
return draftStore.updateDraft({
|
|
442
|
+
draftId,
|
|
443
|
+
identity: options.identity,
|
|
444
|
+
payload,
|
|
445
|
+
expectedRevision: draftOpts?.expectedRevision,
|
|
446
|
+
expectedConcurrencyToken: draftOpts?.concurrencyToken,
|
|
447
|
+
});
|
|
448
|
+
},
|
|
449
|
+
approveDraft(approval) {
|
|
450
|
+
return draftStore.approveDraft({
|
|
451
|
+
draftId: approval.draftId,
|
|
452
|
+
identity: options.identity,
|
|
453
|
+
approval,
|
|
454
|
+
});
|
|
455
|
+
},
|
|
456
|
+
markDraft(draftId, status, concurrencyToken) {
|
|
457
|
+
return draftStore.markDraft({
|
|
458
|
+
draftId,
|
|
459
|
+
identity: options.identity,
|
|
460
|
+
status,
|
|
461
|
+
concurrencyToken,
|
|
462
|
+
});
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
}
|