@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.
- package/README.md +156 -115
- package/dist/index.js +183 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,30 +1,61 @@
|
|
|
1
1
|
# opencode-palantir
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@openontology/opencode-palantir)
|
|
4
|
+
[](https://www.npmjs.com/package/@openontology/opencode-palantir)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
5
10
|
|
|
6
|
-
|
|
11
|
+
OpenCode plugin that provides:
|
|
7
12
|
|
|
8
|
-
-
|
|
9
|
-
-
|
|
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
|
-
|
|
16
|
+
NPM package: https://www.npmjs.com/package/@openontology/opencode-palantir
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Supported OS
|
|
15
19
|
|
|
16
|
-
|
|
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.
|
|
30
|
+
"plugin": ["@openontology/opencode-palantir@^0.1.4"]
|
|
22
31
|
}
|
|
23
32
|
```
|
|
24
33
|
|
|
25
34
|
Restart OpenCode.
|
|
26
35
|
|
|
27
|
-
|
|
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.
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
134
|
+
This package does **not** ship with docs bundled. The docs DB is a local file:
|
|
66
135
|
|
|
67
|
-
|
|
136
|
+
- `data/docs.parquet` (in your repo root)
|
|
68
137
|
|
|
69
|
-
|
|
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
|
|
144
|
+
This downloads the docs and writes `data/docs.parquet`.
|
|
76
145
|
|
|
77
|
-
|
|
146
|
+
### Tools
|
|
78
147
|
|
|
79
|
-
|
|
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
|
-
|
|
153
|
+
If `data/docs.parquet` is missing, both tools will tell you to run `/refresh-docs`.
|
|
82
154
|
|
|
83
|
-
##
|
|
155
|
+
## Foundry MCP helpers
|
|
84
156
|
|
|
85
|
-
|
|
157
|
+
This plugin registers Foundry commands and agents automatically at startup (config-driven).
|
|
86
158
|
|
|
87
|
-
|
|
88
|
-
- **`list_all_docs`** - List all available documentation pages
|
|
159
|
+
### Auto-bootstrap (no command required)
|
|
89
160
|
|
|
90
|
-
If `
|
|
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
|
-
|
|
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
|
-
|
|
95
|
-
gating and Foundry sub-agents:
|
|
168
|
+
### Guided setup and maintenance
|
|
96
169
|
|
|
97
|
-
-
|
|
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
|
-
-
|
|
103
|
-
|
|
104
|
-
-
|
|
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
|
-
|
|
109
|
-
|
|
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
|
-
|
|
224
|
+
### Smoke test the built artifact
|
|
112
225
|
|
|
113
226
|
```bash
|
|
114
|
-
|
|
227
|
+
mise run smoke
|
|
115
228
|
```
|
|
116
229
|
|
|
117
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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).",
|