@openontology/opencode-palantir 0.1.4 → 0.1.5

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.
Files changed (3) hide show
  1. package/README.md +156 -115
  2. package/dist/index.js +183 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,30 +1,61 @@
1
1
  # opencode-palantir
2
2
 
3
- OpenCode plugin that provides **Palantir Foundry documentation** to AI agents via a local Parquet
4
- database.
3
+ [![npm](https://img.shields.io/npm/v/@openontology/opencode-palantir?logo=npm&label=npm)](https://www.npmjs.com/package/@openontology/opencode-palantir)
4
+ [![downloads](https://img.shields.io/npm/dm/@openontology/opencode-palantir?logo=npm&label=downloads)](https://www.npmjs.com/package/@openontology/opencode-palantir)
5
+ ![CI](https://img.shields.io/github/actions/workflow/status/anand-testcompare/opencode-palantir/pr.yml?branch=main&label=CI&logo=github)
6
+ ![bun](https://img.shields.io/badge/bun-1.3.2-000000?logo=bun&logoColor=white)
7
+ ![@opencode-ai/plugin](https://img.shields.io/github/package-json/dependency-version/anand-testcompare/opencode-palantir/dev/%40opencode-ai%2Fplugin?label=opencode%20plugin%20api&logo=npm)
8
+ ![palantir-mcp](https://img.shields.io/npm/v/palantir-mcp?logo=npm&label=palantir-mcp)
9
+ ![hyparquet](https://img.shields.io/github/package-json/dependency-version/anand-testcompare/opencode-palantir/hyparquet?label=hyparquet&logo=npm)
5
10
 
6
- ## Features
11
+ OpenCode plugin that provides:
7
12
 
8
- - Fetches all ~3,600 pages from Palantir's public documentation
9
- - Stores in a local Parquet file for fast offline access (~17MB)
10
- - Exposes `get_doc_page` and `list_all_docs` tools for AI agents
13
+ - Palantir public documentation tools backed by a local Parquet database
14
+ - Foundry MCP bootstrapping helpers (commands, agents, and optional auto-bootstrap)
11
15
 
12
- ## Quick start (OpenCode users)
16
+ NPM package: https://www.npmjs.com/package/@openontology/opencode-palantir
13
17
 
14
- ### 1) Enable the plugin in `opencode.json` / `opencode.jsonc`
18
+ ## Supported OS
15
19
 
16
- Add the plugin to your OpenCode config:
20
+ - Supported: macOS, Linux
21
+ - Windows: not supported (WSL2 might work, but we don’t debug Windows-specific issues)
22
+
23
+ ## Install (OpenCode)
24
+
25
+ Add the plugin in your OpenCode config (`opencode.jsonc`):
17
26
 
18
27
  ```jsonc
19
28
  {
20
29
  "$schema": "https://opencode.ai/config.json",
21
- "plugin": ["@openontology/opencode-palantir@^0.1.1"]
30
+ "plugin": ["@openontology/opencode-palantir@^0.1.4"]
22
31
  }
23
32
  ```
24
33
 
25
34
  Restart OpenCode.
26
35
 
27
- ### 2) (Optional) Install per-project
36
+ After enabling the plugin, OpenCode will automatically register:
37
+
38
+ - Tools: `get_doc_page`, `list_all_docs`
39
+ - Commands: `/refresh-docs`, `/setup-palantir-mcp`, `/rescan-palantir-mcp-tools`
40
+ - Agents: `foundry-librarian`, `foundry`
41
+
42
+ ### Versions: how to get the latest
43
+
44
+ Prefer **pinned** or **semver range** installs (like `@^0.1.4`), and update intentionally.
45
+
46
+ Avoid using `@latest` in config:
47
+
48
+ - it can make startup slower (npm resolution/install on startup)
49
+ - it makes behavior less deterministic
50
+ - depending on caching, you may not get the upgrade behavior you expect
51
+
52
+ To find the newest version and changelog:
53
+
54
+ - NPM versions: https://www.npmjs.com/package/@openontology/opencode-palantir
55
+ - GitHub releases: https://github.com/anand-testcompare/opencode-palantir/releases
56
+ - Repo changelog: `CHANGELOG.md`
57
+
58
+ ### (Optional) Install per-project
28
59
 
29
60
  In your project repo, add the plugin as a dependency inside `.opencode/` (keeps plugin deps separate
30
61
  from your app deps):
@@ -35,7 +66,7 @@ mkdir -p .opencode
35
66
  cat > .opencode/package.json <<'EOF'
36
67
  {
37
68
  "dependencies": {
38
- "@openontology/opencode-palantir": "^0.1.1"
69
+ "@openontology/opencode-palantir": "^0.1.4"
39
70
  }
40
71
  }
41
72
  EOF
@@ -45,8 +76,6 @@ EOF
45
76
 
46
77
  Then create a tiny wrapper file in `.opencode/plugins/`:
47
78
 
48
- Create a tiny wrapper file in `.opencode/plugins/`:
49
-
50
79
  ```bash
51
80
  mkdir -p .opencode/plugins
52
81
 
@@ -59,62 +88,146 @@ EOF
59
88
 
60
89
  OpenCode automatically loads `.js`/`.ts` files from `.opencode/plugins/` at startup.
61
90
 
62
- > If your OpenCode setup uses an `opencode.json` / `opencode.jsonc` that restricts plugin loading,
63
- > make sure `.opencode/plugins/` (or the specific plugin file) is included.
91
+ ## Environment variables (Foundry MCP)
92
+
93
+ This plugin never writes secrets to disk. In `opencode.jsonc`, the token is always referenced as
94
+ `{env:FOUNDRY_TOKEN}`.
95
+
96
+ ### Variables
97
+
98
+ - `FOUNDRY_URL`
99
+ - Foundry base URL (used for auto-bootstrap and can be used as a default for `/setup-palantir-mcp`)
100
+ - Example: `https://YOUR-STACK.palantirfoundry.com`
101
+ - `FOUNDRY_TOKEN`
102
+ - Foundry token used by `palantir-mcp` for tool discovery
103
+ - Must be exported (not just set in a shell)
104
+
105
+ ### Recommended setup (zsh, macOS/Linux)
106
+
107
+ Use your existing shell secrets file. For example, if you already source `~/.shell_secrets` from
108
+ `~/.zshrc`, add:
109
+
110
+ ```zsh
111
+ export FOUNDRY_URL='https://YOUR-STACK.palantirfoundry.com'
112
+ export FOUNDRY_TOKEN='YOUR_TOKEN'
113
+ ```
114
+
115
+ Lock it down:
116
+
117
+ ```bash
118
+ chmod 600 ~/.shell_secrets
119
+ ```
120
+
121
+ Ensure `~/.zshrc` sources it:
122
+
123
+ ```zsh
124
+ if [ -f "$HOME/.shell_secrets" ]; then
125
+ source "$HOME/.shell_secrets"
126
+ fi
127
+ ```
128
+
129
+ If you still see “token not exported” errors, verify `echo $FOUNDRY_TOKEN` prints a value and that
130
+ it’s `export`ed in the environment where OpenCode is launched.
131
+
132
+ ## Docs tools (Palantir public docs)
64
133
 
65
- ### 3) Get `docs.parquet`
134
+ This package does **not** ship with docs bundled. The docs DB is a local file:
66
135
 
67
- This package does **not** ship with docs bundled. You have two options:
136
+ - `data/docs.parquet` (in your repo root)
68
137
 
69
- #### Option A (recommended): fetch inside OpenCode
138
+ ### Fetch docs
70
139
 
71
140
  In OpenCode, run:
72
141
 
73
142
  - `/refresh-docs`
74
143
 
75
- This downloads the docs and writes them to `data/docs.parquet` in your project root.
144
+ This downloads the docs and writes `data/docs.parquet`.
76
145
 
77
- #### Option B: download a prebuilt Parquet file
146
+ ### Tools
78
147
 
79
- Download `data/docs.parquet` from this GitHub repo and place it at:
148
+ - `get_doc_page`
149
+ - Retrieve a doc page by URL, or fuzzy match by query
150
+ - `list_all_docs`
151
+ - List docs with pagination and optional query/scope filtering
80
152
 
81
- - `<your-project>/data/docs.parquet`
153
+ If `data/docs.parquet` is missing, both tools will tell you to run `/refresh-docs`.
82
154
 
83
- ## Using the tools
155
+ ## Foundry MCP helpers
84
156
 
85
- When installed, this plugin exposes:
157
+ This plugin registers Foundry commands and agents automatically at startup (config-driven).
86
158
 
87
- - **`get_doc_page`** - Retrieve a specific doc page by URL
88
- - **`list_all_docs`** - List all available documentation pages
159
+ ### Auto-bootstrap (no command required)
89
160
 
90
- If `data/docs.parquet` is missing, both tools will instruct you to run `/refresh-docs`.
161
+ If you set both `FOUNDRY_TOKEN` and `FOUNDRY_URL`, the plugin will automatically and idempotently
162
+ patch repo-root `opencode.jsonc` to initialize:
91
163
 
92
- ## Foundry MCP setup helpers
164
+ - `mcp.palantir-mcp` local server config
165
+ - global tool deny: `tools.palantir-mcp_* = false`
166
+ - per-agent allow/deny toggles under `foundry-librarian` and `foundry`
93
167
 
94
- This plugin also provides two OpenCode commands to set up `palantir-mcp` with project-scoped tool
95
- gating and Foundry sub-agents:
168
+ ### Guided setup and maintenance
96
169
 
97
- - **`/setup-palantir-mcp <foundry_api_url>`**
170
+ - `/setup-palantir-mcp <foundry_api_url>`
98
171
  - Creates/patches repo-root `opencode.jsonc`
99
172
  - Adds `mcp.palantir-mcp` (if missing) as a local `npx palantir-mcp --foundry-api-url ...` server
100
173
  - Enforces global deny: `tools.palantir-mcp_* = false`
101
174
  - Creates `foundry-librarian` and `foundry` agents
102
- - Dynamically discovers the current `palantir-mcp` tool list and writes explicit `true/false`
103
- per-tool toggles under each Foundry agent
104
- - **`/rescan-palantir-mcp-tools`**
105
- - Re-discovers the `palantir-mcp` tool list and adds any missing explicit toggles
175
+ - Discovers `palantir-mcp` tools and writes explicit `true/false` toggles under each agent
176
+ - `/rescan-palantir-mcp-tools`
177
+ - Re-discovers the `palantir-mcp` tool list and adds missing explicit toggles
106
178
  - Never overwrites existing `palantir-mcp_*` toggles
107
179
 
108
- Auth is always env-only. The token is referenced as `{env:FOUNDRY_TOKEN}` and is never written to
109
- disk.
180
+ ### About palantir-mcp versions (important)
181
+
182
+ The generated MCP server uses `npx -y palantir-mcp ...` by default.
183
+
184
+ Notes:
185
+
186
+ - First run can be slow (npx may need to download/install).
187
+ - `@latest` / unpinned installs are less deterministic.
188
+
189
+ Recommendation: once you’re set up, pin the version in `opencode.jsonc`:
190
+
191
+ ```jsonc
192
+ {
193
+ "mcp": {
194
+ "palantir-mcp": {
195
+ "type": "local",
196
+ "command": [
197
+ "npx",
198
+ "-y",
199
+ "palantir-mcp@<version>",
200
+ "--foundry-api-url",
201
+ "https://YOUR-STACK.palantirfoundry.com"
202
+ ]
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ ## Development (this repo)
209
+
210
+ ### Setup
211
+
212
+ ```bash
213
+ mise run setup
214
+ ```
215
+
216
+ ### Common tasks
217
+
218
+ - Build: `mise run build`
219
+ - Test: `mise run test`
220
+ - Lint: `mise run lint`
221
+ - Typecheck: `mise run typecheck`
222
+ - Format: `mise run format`
110
223
 
111
- ## Setup (this repo)
224
+ ### Smoke test the built artifact
112
225
 
113
226
  ```bash
114
- bun install
227
+ mise run smoke
115
228
  ```
116
229
 
117
- ## Fetching Documentation
230
+ ### Fetch docs parquet (local dev)
118
231
 
119
232
  Fetch all Palantir docs into `data/docs.parquet` (~2 minutes, ~17MB file):
120
233
 
@@ -122,9 +235,7 @@ Fetch all Palantir docs into `data/docs.parquet` (~2 minutes, ~17MB file):
122
235
  bun run src/docs/fetch-cli.ts
123
236
  ```
124
237
 
125
- ## Querying the Data
126
-
127
- ### Schema
238
+ ### Parquet schema (local dev)
128
239
 
129
240
  The Parquet file contains a single row group with the following columns:
130
241
 
@@ -137,7 +248,7 @@ The Parquet file contains a single row group with the following columns:
137
248
  | `meta` | string | JSON-encoded metadata |
138
249
  | `fetched_at` | string | ISO 8601 timestamp of when fetched |
139
250
 
140
- ### Bun
251
+ Example (Bun):
141
252
 
142
253
  ```typescript
143
254
  import { parquetReadObjects } from 'hyparquet';
@@ -147,76 +258,6 @@ const file = await Bun.file('data/docs.parquet').arrayBuffer();
147
258
  // List all pages (url + title only)
148
259
  const pages = await parquetReadObjects({ file, columns: ['url', 'title'] });
149
260
  console.log(`${pages.length} pages`);
150
-
151
- // Search by title
152
- const matches = pages.filter((p) => p.title.includes('Pipeline'));
153
- console.log(matches.slice(0, 10));
154
-
155
- // Get a specific page's content by row index
156
- const urlToRow = new Map(pages.map((p, i) => [p.url, i]));
157
- const rowIndex = urlToRow.get('/foundry/ontology/overview/');
158
- if (rowIndex !== undefined) {
159
- const [page] = await parquetReadObjects({
160
- file,
161
- rowStart: rowIndex,
162
- rowEnd: rowIndex + 1,
163
- });
164
- console.log(page.content);
165
- }
166
- ```
167
-
168
- ## OpenCode Tools
169
-
170
- When installed as an OpenCode plugin, exposes:
171
-
172
- - **`get_doc_page`** - Retrieve a specific doc page by URL
173
- - **`list_all_docs`** - List all available documentation pages
174
- - **`/refresh-docs`** - Command hook to re-fetch all documentation
175
-
176
- ### Installing in OpenCode (this repo only)
177
-
178
- For local development against `dist/`, you can point the wrapper at the built artifact:
179
-
180
- ```bash
181
- mkdir -p .opencode/plugins
182
-
183
- cat > .opencode/plugins/opencode-palantir.js <<'EOF'
184
- import plugin from '../../dist/index.js';
185
-
186
- export default plugin;
187
- EOF
188
- ```
189
-
190
- ## Development
191
-
192
- Build the plugin:
193
-
194
- ```bash
195
- mise run build
196
- ```
197
-
198
- Run tests:
199
-
200
- ```bash
201
- mise run test
202
- ```
203
-
204
- Smoke test the built artifact (build + verify tools load from `dist/index.js`):
205
-
206
- ```bash
207
- mise run smoke
208
- ```
209
-
210
- Lint code:
211
-
212
- ```bash
213
- mise run lint
214
- ```
215
-
216
- Format with Prettier:
217
-
218
- ```bash
219
- mise run format
220
261
  ```
221
262
 
222
263
  ## Release notes
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // src/index.ts
3
- import { tool } from "@opencode-ai/plugin/tool";
4
3
  import path4 from "path";
4
+ import { tool } from "@opencode-ai/plugin/tool";
5
5
 
6
6
  // node_modules/hyparquet/src/constants.js
7
7
  var ParquetTypes = [
@@ -7869,6 +7869,20 @@ function formatError3(err) {
7869
7869
  function isRecord2(value) {
7870
7870
  return !!value && typeof value === "object" && !Array.isArray(value);
7871
7871
  }
7872
+ function stableSortJson(value) {
7873
+ if (Array.isArray(value))
7874
+ return value.map(stableSortJson);
7875
+ if (!isRecord2(value))
7876
+ return value;
7877
+ const out = {};
7878
+ for (const k of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
7879
+ out[k] = stableSortJson(value[k]);
7880
+ }
7881
+ return out;
7882
+ }
7883
+ function stableJsonStringify(value) {
7884
+ return JSON.stringify(stableSortJson(value));
7885
+ }
7872
7886
  function formatWarnings(warnings) {
7873
7887
  if (warnings.length === 0)
7874
7888
  return "";
@@ -7902,8 +7916,81 @@ async function resolveProfile(worktree) {
7902
7916
  };
7903
7917
  }
7904
7918
  }
7919
+ function hasPalantirToolToggles(data, agentName) {
7920
+ const agents = data["agent"];
7921
+ if (!isRecord2(agents))
7922
+ return false;
7923
+ const agent = agents[agentName];
7924
+ if (!isRecord2(agent))
7925
+ return false;
7926
+ const tools = agent["tools"];
7927
+ if (!isRecord2(tools))
7928
+ return false;
7929
+ return Object.keys(tools).some((k) => k.startsWith("palantir-mcp_"));
7930
+ }
7931
+ function isAutoBootstrapAlreadyComplete(data) {
7932
+ const foundryUrl = extractFoundryApiUrlFromMcpConfig(data);
7933
+ const toolsRoot = data["tools"];
7934
+ const hasGlobalDeny = isRecord2(toolsRoot) && toolsRoot["palantir-mcp_*"] === false;
7935
+ const hasAgentToggles = hasPalantirToolToggles(data, "foundry-librarian") && hasPalantirToolToggles(data, "foundry");
7936
+ return !!foundryUrl && hasGlobalDeny && hasAgentToggles;
7937
+ }
7938
+ async function autoBootstrapPalantirMcpIfConfigured(worktree) {
7939
+ try {
7940
+ const tokenRaw = process.env.FOUNDRY_TOKEN;
7941
+ const urlRaw = process.env.FOUNDRY_URL;
7942
+ if (!tokenRaw || tokenRaw.trim().length === 0)
7943
+ return;
7944
+ if (!urlRaw || urlRaw.trim().length === 0)
7945
+ return;
7946
+ const normalized = normalizeFoundryBaseUrl(urlRaw);
7947
+ if ("error" in normalized)
7948
+ return;
7949
+ const readJsonc = await readOpencodeJsonc(worktree);
7950
+ if (!readJsonc.ok && !("missing" in readJsonc))
7951
+ return;
7952
+ const readLegacy = await readLegacyOpencodeJson(worktree);
7953
+ if (!readLegacy.ok && !("missing" in readLegacy))
7954
+ return;
7955
+ const baseJsoncData = readJsonc.ok ? readJsonc.data : {};
7956
+ const base = isRecord2(baseJsoncData) ? baseJsoncData : {};
7957
+ const merged = readLegacy.ok ? mergeLegacyIntoJsonc(readLegacy.data, base) : { ...base };
7958
+ if (isAutoBootstrapAlreadyComplete(merged))
7959
+ return;
7960
+ const existingMcpUrlRaw = extractFoundryApiUrlFromMcpConfig(merged);
7961
+ const existingMcpUrlNorm = existingMcpUrlRaw ? normalizeFoundryBaseUrl(existingMcpUrlRaw) : null;
7962
+ const { profile } = await resolveProfile(worktree);
7963
+ const discoveryUrl = existingMcpUrlNorm && "url" in existingMcpUrlNorm ? existingMcpUrlNorm.url : normalized.url;
7964
+ const toolNames = await listPalantirMcpTools(discoveryUrl);
7965
+ if (toolNames.length === 0)
7966
+ return;
7967
+ const allowlist = computeAllowedTools(profile, toolNames);
7968
+ const patch = patchConfigForSetup(merged, {
7969
+ foundryApiUrl: normalized.url,
7970
+ toolNames,
7971
+ profile,
7972
+ allowlist
7973
+ });
7974
+ const jsoncMissing = !readJsonc.ok && "missing" in readJsonc;
7975
+ const needsMigration = jsoncMissing && readLegacy.ok;
7976
+ const changed = needsMigration || stableJsonStringify(merged) !== stableJsonStringify(patch.data);
7977
+ if (!changed)
7978
+ return;
7979
+ const outPath = path3.join(worktree, OPENCODE_JSONC_FILENAME);
7980
+ const text = stringifyJsonc(patch.data);
7981
+ await writeFileAtomic(outPath, text);
7982
+ if (readLegacy.ok) {
7983
+ await renameLegacyToBak(worktree);
7984
+ }
7985
+ } catch (err) {
7986
+ return;
7987
+ }
7988
+ }
7905
7989
  async function setupPalantirMcp(worktree, rawArgs) {
7906
- const urlArg = rawArgs.trim();
7990
+ const urlFromArgs = rawArgs.trim();
7991
+ const urlFromEnvRaw = process.env.FOUNDRY_URL;
7992
+ const urlFromEnv = typeof urlFromEnvRaw === "string" ? urlFromEnvRaw.trim() : "";
7993
+ const urlArg = urlFromArgs || urlFromEnv;
7907
7994
  if (!urlArg) {
7908
7995
  return [
7909
7996
  "[ERROR] Missing Foundry base URL.",
@@ -7911,6 +7998,9 @@ async function setupPalantirMcp(worktree, rawArgs) {
7911
7998
  "Usage:",
7912
7999
  " /setup-palantir-mcp <foundry_api_url>",
7913
8000
  "",
8001
+ "Or set:",
8002
+ " export FOUNDRY_URL=<foundry_api_url>",
8003
+ "",
7914
8004
  "Example:",
7915
8005
  " /setup-palantir-mcp https://23dimethyl.usw-3.palantirfoundry.com"
7916
8006
  ].join(`
@@ -8056,6 +8146,92 @@ var NO_DB_MESSAGE = "Documentation database not found. Run /refresh-docs to down
8056
8146
  var plugin = async (input) => {
8057
8147
  const dbPath = path4.join(input.worktree, "data", "docs.parquet");
8058
8148
  let dbInstance = null;
8149
+ let autoBootstrapStarted = false;
8150
+ function ensureCommandDefinitions(cfg) {
8151
+ if (!cfg.command)
8152
+ cfg.command = {};
8153
+ if (!cfg.command["refresh-docs"]) {
8154
+ cfg.command["refresh-docs"] = {
8155
+ template: "Refresh Palantir documentation database.",
8156
+ description: "Download Palantir docs and write data/docs.parquet (local)."
8157
+ };
8158
+ }
8159
+ if (!cfg.command["setup-palantir-mcp"]) {
8160
+ cfg.command["setup-palantir-mcp"] = {
8161
+ template: "Set up palantir-mcp for this repo.",
8162
+ description: "Guided MCP setup for Foundry. Usage: /setup-palantir-mcp <foundry_api_url>. Requires FOUNDRY_TOKEN for tool discovery."
8163
+ };
8164
+ }
8165
+ if (!cfg.command["rescan-palantir-mcp-tools"]) {
8166
+ cfg.command["rescan-palantir-mcp-tools"] = {
8167
+ template: "Re-scan palantir-mcp tools and patch tool gating.",
8168
+ description: "Re-discovers the palantir-mcp tool list and adds missing palantir-mcp_* toggles (does not overwrite existing toggles). Requires FOUNDRY_TOKEN."
8169
+ };
8170
+ }
8171
+ }
8172
+ function ensureAgentDefaults2(agent, agentName) {
8173
+ const defaultDescription = agentName === "foundry-librarian" ? "Foundry exploration and context gathering (parallel-friendly)" : "Foundry execution agent (uses only enabled palantir-mcp tools)";
8174
+ if (agent.mode !== "subagent" && agent.mode !== "primary" && agent.mode !== "all") {
8175
+ agent.mode = "subagent";
8176
+ }
8177
+ if (typeof agent["hidden"] !== "boolean")
8178
+ agent["hidden"] = false;
8179
+ if (typeof agent.description !== "string")
8180
+ agent.description = defaultDescription;
8181
+ if (typeof agent.prompt !== "string") {
8182
+ agent.prompt = agentName === "foundry-librarian" ? [
8183
+ "You are the Foundry librarian.",
8184
+ "",
8185
+ "- Focus on exploration and context gathering.",
8186
+ "- Split independent exploration tasks and run them in parallel when possible.",
8187
+ "- Return compact summaries and cite the tool calls you ran.",
8188
+ "- Avoid dumping massive schemas unless explicitly asked."
8189
+ ].join(`
8190
+ `) : [
8191
+ "You are the Foundry execution agent.",
8192
+ "",
8193
+ "- Use only enabled palantir-mcp tools.",
8194
+ "- Prefer working from summaries produced by @foundry-librarian.",
8195
+ "- Keep operations focused and deterministic."
8196
+ ].join(`
8197
+ `);
8198
+ }
8199
+ if (!agent.tools)
8200
+ agent.tools = {};
8201
+ if (agentName === "foundry-librarian") {
8202
+ if (agent.tools.get_doc_page === undefined)
8203
+ agent.tools.get_doc_page = true;
8204
+ if (agent.tools.list_all_docs === undefined)
8205
+ agent.tools.list_all_docs = true;
8206
+ return;
8207
+ }
8208
+ if (agent.tools.get_doc_page === undefined)
8209
+ agent.tools.get_doc_page = false;
8210
+ if (agent.tools.list_all_docs === undefined)
8211
+ agent.tools.list_all_docs = false;
8212
+ }
8213
+ function ensureAgentDefinitions(cfg) {
8214
+ if (!cfg.agent)
8215
+ cfg.agent = {};
8216
+ const librarian = cfg.agent["foundry-librarian"] ?? {};
8217
+ ensureAgentDefaults2(librarian, "foundry-librarian");
8218
+ cfg.agent["foundry-librarian"] = librarian;
8219
+ const foundry = cfg.agent.foundry ?? {};
8220
+ ensureAgentDefaults2(foundry, "foundry");
8221
+ cfg.agent.foundry = foundry;
8222
+ }
8223
+ function maybeStartAutoBootstrap() {
8224
+ if (autoBootstrapStarted)
8225
+ return;
8226
+ const token = process.env.FOUNDRY_TOKEN;
8227
+ const url = process.env.FOUNDRY_URL;
8228
+ if (!token || token.trim().length === 0)
8229
+ return;
8230
+ if (!url || url.trim().length === 0)
8231
+ return;
8232
+ autoBootstrapStarted = true;
8233
+ autoBootstrapPalantirMcpIfConfigured(input.worktree);
8234
+ }
8059
8235
  async function getDb() {
8060
8236
  if (!dbInstance) {
8061
8237
  dbInstance = await createDatabase(dbPath);
@@ -8159,6 +8335,11 @@ var plugin = async (input) => {
8159
8335
  return score;
8160
8336
  }
8161
8337
  return {
8338
+ config: async (cfg) => {
8339
+ ensureCommandDefinitions(cfg);
8340
+ ensureAgentDefinitions(cfg);
8341
+ maybeStartAutoBootstrap();
8342
+ },
8162
8343
  tool: {
8163
8344
  get_doc_page: tool({
8164
8345
  description: "Retrieve a Palantir documentation page. Provide either a URL path (preferred) or a free-text query; the tool will handle common URL variants (full URLs, missing /docs prefix, trailing slashes).",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openontology/opencode-palantir",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "collection of tools, agents, hooks to supercharge development in foundry",
5
5
  "license": "MIT",
6
6
  "author": {