@jagilber-org/index-server 1.28.10 → 1.28.19
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 +109 -1
- package/CONTRIBUTING.md +13 -0
- package/README.md +10 -14
- package/dist/config/featureConfig.js +4 -1
- package/dist/dashboard/client/admin.html +69 -29
- package/dist/dashboard/client/js/admin.embeddings.js +97 -5
- package/dist/dashboard/client/js/admin.instructions.js +1 -1
- package/dist/dashboard/server/AdminPanel.js +38 -0
- package/dist/dashboard/server/ApiRoutes.js +14 -1
- package/dist/dashboard/server/routes/embeddings.routes.js +76 -1
- package/dist/dashboard/server/routes/instructions.routes.js +4 -11
- package/dist/dashboard/server/routes/scripts.routes.js +35 -10
- package/dist/dashboard/server/routes/status.routes.js +77 -0
- package/dist/models/instruction.d.ts +2 -1
- package/dist/models/instruction.js +2 -0
- package/dist/schemas/index-server.code-schema.json +52478 -0
- package/dist/schemas/index.d.ts +7 -164
- package/dist/schemas/index.js +45 -63
- package/dist/schemas/instructionSchema.d.ts +46 -0
- package/dist/schemas/instructionSchema.js +159 -0
- package/{schemas → dist/schemas}/json-schema/instruction-content-type.schema.json +6 -4
- package/{schemas → dist/schemas}/json-schema/instruction-instruction-entry.schema.json +6 -4
- package/dist/schemas/manifest.json +78 -0
- package/dist/server/index-server.js +7 -1
- package/dist/services/bootstrapGating.js +2 -2
- package/dist/services/handlers/instructions.add.js +18 -0
- package/dist/services/handlers/instructions.groom.js +6 -1
- package/dist/services/handlers/instructions.import.js +42 -7
- package/dist/services/handlers.activation.js +3 -1
- package/dist/services/handlers.dashboardConfig.js +2 -1
- package/dist/services/handlers.feedback.d.ts +4 -4
- package/dist/services/handlers.feedback.js +390 -27
- package/dist/services/handlers.instructionSchema.js +73 -31
- package/dist/services/handlers.search.js +11 -6
- package/dist/services/indexLoader.js +7 -0
- package/dist/services/instructionRecordValidation.js +32 -84
- package/dist/services/mcpConfig/flagCatalog.d.ts +1 -1
- package/dist/services/mcpConfig/flagCatalog.js +2 -0
- package/dist/services/mcpConfig/formats.js +2 -6
- package/dist/services/seedBootstrap.contentModel.d.ts +13 -0
- package/dist/services/seedBootstrap.contentModel.js +166 -0
- package/dist/services/seedBootstrap.contentTypes.d.ts +5 -0
- package/dist/services/seedBootstrap.contentTypes.js +76 -0
- package/dist/services/seedBootstrap.d.ts +1 -0
- package/dist/services/seedBootstrap.js +87 -10
- package/dist/services/toolRegistry.js +52 -24
- package/dist/services/toolRegistry.zod.js +84 -37
- package/dist/versioning/schemaVersion.d.ts +1 -1
- package/dist/versioning/schemaVersion.js +1 -13
- package/package.json +17 -3
- package/schemas/index-server.code-schema.json +31019 -25047
- package/schemas/instruction.schema.json +16 -6
- package/schemas/manifest.json +3 -3
- package/scripts/README.md +20 -0
- package/scripts/build/README.md +41 -0
- package/scripts/build/setup-wizard-paths.mjs +27 -0
- package/scripts/build/setup-wizard.mjs +7 -21
- package/scripts/client/README.md +26 -0
- package/scripts/client/index-server-client.ps1 +203 -0
- package/scripts/client/index-server-client.sh +149 -0
- package/scripts/client/powershell-mcp-server.ps1 +83 -0
- package/scripts/client/powershell-mcp-template.ps1 +85 -0
- package/scripts/hooks/README.md +40 -0
- package/server.json +2 -2
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-persisted-admin-session.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-persisted-session-history-entry.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-persisted-web-socket-connection.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-session-persistence-config.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-session-persistence-data.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-session-persistence-manifest.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/SessionPersistence-session-persistence-metadata.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/instruction-audience-scope.schema.json +0 -0
- /package/{schemas → dist/schemas}/json-schema/instruction-requirement-level.schema.json +0 -0
|
@@ -132,26 +132,30 @@
|
|
|
132
132
|
},
|
|
133
133
|
"contentType": {
|
|
134
134
|
"enum": [
|
|
135
|
+
"agent",
|
|
136
|
+
"skill",
|
|
135
137
|
"instruction",
|
|
136
|
-
"
|
|
138
|
+
"prompt",
|
|
137
139
|
"workflow",
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
140
|
+
"knowledge",
|
|
141
|
+
"template",
|
|
142
|
+
"integration"
|
|
141
143
|
],
|
|
142
144
|
"default": "instruction",
|
|
143
|
-
"description": "Content type classification: instruction (actionable guidance),
|
|
145
|
+
"description": "Content type classification: agent (AI agent definitions and personas), skill (packaged agent capabilities or callable skills), instruction (actionable guidance and operating rules), prompt (prompt templates or prompt engineering assets), workflow (multi-step processes or runbooks), knowledge (reference material, examples, concepts, and documentation), template (reusable scaffolds or structured content templates), integration (external system, MCP, API, or tool integration guidance)."
|
|
144
146
|
},
|
|
145
147
|
"schemaVersion": {
|
|
146
148
|
"type": "string",
|
|
147
149
|
"enum": [
|
|
148
|
-
"
|
|
150
|
+
"6"
|
|
149
151
|
],
|
|
152
|
+
"x-fieldClass": "server-managed",
|
|
150
153
|
"description": "Internal schema version for migration"
|
|
151
154
|
},
|
|
152
155
|
"sourceHash": {
|
|
153
156
|
"type": "string",
|
|
154
157
|
"pattern": "^[a-f0-9]{64}$",
|
|
158
|
+
"x-fieldClass": "server-managed",
|
|
155
159
|
"description": "SHA256 hash of body for drift detection"
|
|
156
160
|
},
|
|
157
161
|
"deprecatedBy": {
|
|
@@ -161,26 +165,31 @@
|
|
|
161
165
|
"createdAt": {
|
|
162
166
|
"type": "string",
|
|
163
167
|
"format": "date-time",
|
|
168
|
+
"x-fieldClass": "server-managed",
|
|
164
169
|
"description": "Creation timestamp (ISO 8601)"
|
|
165
170
|
},
|
|
166
171
|
"updatedAt": {
|
|
167
172
|
"type": "string",
|
|
168
173
|
"format": "date-time",
|
|
174
|
+
"x-fieldClass": "server-managed",
|
|
169
175
|
"description": "Last mutation timestamp (ISO 8601)"
|
|
170
176
|
},
|
|
171
177
|
"usageCount": {
|
|
172
178
|
"type": "integer",
|
|
173
179
|
"minimum": 0,
|
|
180
|
+
"x-fieldClass": "server-managed",
|
|
174
181
|
"description": "Number of tracked usage events"
|
|
175
182
|
},
|
|
176
183
|
"firstSeenTs": {
|
|
177
184
|
"type": "string",
|
|
178
185
|
"format": "date-time",
|
|
186
|
+
"x-fieldClass": "server-managed",
|
|
179
187
|
"description": "Timestamp when usage was first observed (ISO 8601)"
|
|
180
188
|
},
|
|
181
189
|
"lastUsedAt": {
|
|
182
190
|
"type": "string",
|
|
183
191
|
"format": "date-time",
|
|
192
|
+
"x-fieldClass": "server-managed",
|
|
184
193
|
"description": "Last usage timestamp (ISO 8601)"
|
|
185
194
|
},
|
|
186
195
|
"riskScore": {
|
|
@@ -270,6 +279,7 @@
|
|
|
270
279
|
"archivedAt": {
|
|
271
280
|
"type": "string",
|
|
272
281
|
"format": "date-time",
|
|
282
|
+
"x-fieldClass": "server-managed",
|
|
273
283
|
"description": "Timestamp when archived (ISO 8601)"
|
|
274
284
|
},
|
|
275
285
|
"semanticSummary": {
|
package/schemas/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generatedAt": "2026-
|
|
2
|
+
"version": "1.28.19",
|
|
3
|
+
"generatedAt": "2026-05-11T01:35:27.991Z",
|
|
4
4
|
"trackedDir": "schemas",
|
|
5
5
|
"distDir": "dist/schemas",
|
|
6
6
|
"jsonSchemas": [
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"src",
|
|
68
68
|
"scripts"
|
|
69
69
|
],
|
|
70
|
-
"fileCount":
|
|
70
|
+
"fileCount": 266,
|
|
71
71
|
"features": {
|
|
72
72
|
"jsdoc": true,
|
|
73
73
|
"lineNumbers": true,
|
package/scripts/README.md
CHANGED
|
@@ -10,6 +10,7 @@ Organized by purpose. Each subdirectory has a clear role; naming conventions mak
|
|
|
10
10
|
| `ci/` | CI-specific runners and validation | — |
|
|
11
11
|
| `client/` | Client CLI tools and wizards | — |
|
|
12
12
|
| `deploy/` | Deployment and production ops | `deploy-*`, `smoke-*`, `prod-*` |
|
|
13
|
+
| `dev/` | Dev-server orchestrator + probes (see below) | — |
|
|
13
14
|
| `diagnostics/` | Adhoc probes, health checks, inspection | `adhoc-*` for one-off probes |
|
|
14
15
|
| `dist/` | Distributable scripts (shipped to users) | — |
|
|
15
16
|
| `governance/` | Guards, validators, lint, coverage | `guard-*`, `check-*`, `validate-*` |
|
|
@@ -19,6 +20,25 @@ Organized by purpose. Each subdirectory has a clear role; naming conventions mak
|
|
|
19
20
|
| `perf/` | Performance baselines, trends, benchmarks | `perf-*`, `benchmark-*`, `stress-*` |
|
|
20
21
|
| `testing/` | Test runners, helpers, fixtures | `test-*`, `run-*`, `seed-*` |
|
|
21
22
|
|
|
23
|
+
Root-level PowerShell files under `scripts/` are compatibility wrappers for
|
|
24
|
+
template-managed paths. Prefer the categorized subdirectory implementation for
|
|
25
|
+
new logic.
|
|
26
|
+
|
|
27
|
+
## Dev-server layout
|
|
28
|
+
|
|
29
|
+
`dev/` contains the profile-sandboxed dev orchestrator and its probes, organized
|
|
30
|
+
by role:
|
|
31
|
+
|
|
32
|
+
| Subdirectory | Role | Scripts |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `dev/` | Orchestrator | `dev-server.ps1` |
|
|
35
|
+
| `dev/transport/` | Shared harness | `mcp-stdio.mjs` |
|
|
36
|
+
| `dev/diagnostic/` | Read-only probes | `info-probe.mjs`, `shape-probe.mjs` |
|
|
37
|
+
| `dev/integrity/` | Mutation + verify probes | `crud-probe.mjs`, `disk-server-consistency.mjs`, `io-matrix.mjs` |
|
|
38
|
+
| `dev/util/` | CLI utilities | `io-helper.mjs` |
|
|
39
|
+
|
|
40
|
+
> See `scripts/dev/README.md` for the full dev-server runbook.
|
|
41
|
+
|
|
22
42
|
## Naming Conventions
|
|
23
43
|
|
|
24
44
|
- **`adhoc-*`** — One-off diagnostic probes. Never referenced by CI or `package.json`. Safe to run manually during debugging; safe to delete when no longer needed.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# scripts/build
|
|
2
|
+
|
|
3
|
+
Build, release, schema generation, and publishing tools. Scripts here produce
|
|
4
|
+
artifacts — compiled output, docs, schemas, manifests — and drive the release
|
|
5
|
+
pipeline. Most are wired to `npm run` tasks or called by `Invoke-ReleaseWorkflow.ps1`.
|
|
6
|
+
|
|
7
|
+
## Scripts
|
|
8
|
+
|
|
9
|
+
| Script | Purpose |
|
|
10
|
+
|--------|---------|
|
|
11
|
+
| `build.ps1` | Full build wrapper: `tsc` + asset copy |
|
|
12
|
+
| `ci-build.mjs` | CI-mode build with strict exit codes |
|
|
13
|
+
| `bump-version.mjs` | Bump `package.json` version; commits and tags |
|
|
14
|
+
| `bump-version.ps1` | PowerShell wrapper around `bump-version.mjs` |
|
|
15
|
+
| `copy-dashboard-assets.mjs` | Copy dashboard HTML/JS/CSS into `dist/` |
|
|
16
|
+
| `generate-certs.mjs` | Generate self-signed TLS certs for local HTTPS |
|
|
17
|
+
| `generate-drift-report.mjs` | Compare current schema vs last snapshot; report drift |
|
|
18
|
+
| `generate-manifest.mjs` | Regenerate `schemas/manifest.json` from source |
|
|
19
|
+
| `generate-schemas.mjs` | Regenerate all JSON schemas from TypeScript types |
|
|
20
|
+
| `generate-tools-doc.mjs` | Regenerate `docs/TOOLS-GENERATED.md` from tool registry |
|
|
21
|
+
| `generate-tools-snapshot.mjs` | Capture current tool-registry snapshot for drift checks |
|
|
22
|
+
| `Invoke-ReleaseWorkflow.ps1` | End-to-end release: bump → build → publish → tag |
|
|
23
|
+
| `publish-direct-to-remote.cjs` | Publish build artifacts directly to the remote mirror |
|
|
24
|
+
| `Publish-ToMirror.ps1` | Copy clean-room build to the production mirror path |
|
|
25
|
+
| `set-registry.mjs` | Switch npm registry for publish (scoped packages) |
|
|
26
|
+
| `setup-wizard.mjs` | Interactive first-run setup wizard |
|
|
27
|
+
| `setup-wizard-paths.mjs` | Path resolution helpers for the setup wizard |
|
|
28
|
+
| `sync-constitution.ps1` | Regenerate `constitution.md` from `constitution.json` |
|
|
29
|
+
| `sync-dist.ps1` | Sync `dist/` to production deployment path |
|
|
30
|
+
| `append-agent-provenance.ps1` | Append agent provenance metadata to release artifacts |
|
|
31
|
+
| `Compare-TemplateSpec.ps1` | Diff current template against canonical spec |
|
|
32
|
+
|
|
33
|
+
## Key entry point
|
|
34
|
+
|
|
35
|
+
```pwsh
|
|
36
|
+
# Full release (bump → build → publish → tag)
|
|
37
|
+
pwsh -File scripts/build/Invoke-ReleaseWorkflow.ps1
|
|
38
|
+
|
|
39
|
+
# CI-compatible build with artifact verification
|
|
40
|
+
npm run build:ci
|
|
41
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup-wizard-paths.mjs — Platform-standard per-user data directory resolver.
|
|
3
|
+
*
|
|
4
|
+
* Exported so the setup wizard and tests share a single source of truth.
|
|
5
|
+
*
|
|
6
|
+
* Convention (env-paths style; matches VS Code, npm, gh CLI):
|
|
7
|
+
* Windows: %LOCALAPPDATA%\index-server (default ~\AppData\Local\index-server)
|
|
8
|
+
* macOS: ~/Library/Application Support/index-server
|
|
9
|
+
* Linux: ${XDG_DATA_HOME:-~/.local/share}/index-server
|
|
10
|
+
*/
|
|
11
|
+
import path from 'path';
|
|
12
|
+
|
|
13
|
+
const APP_NAME = 'index-server';
|
|
14
|
+
|
|
15
|
+
/** @param {NodeJS.Platform} [platform] @param {NodeJS.ProcessEnv} [env] */
|
|
16
|
+
export function defaultUserRoot(platform = process.platform, env = process.env) {
|
|
17
|
+
const home = env.HOME || env.USERPROFILE || '';
|
|
18
|
+
if (platform === 'win32') {
|
|
19
|
+
const base = env.LOCALAPPDATA || (home ? path.join(home, 'AppData', 'Local') : '');
|
|
20
|
+
return path.join(base, APP_NAME);
|
|
21
|
+
}
|
|
22
|
+
if (platform === 'darwin') {
|
|
23
|
+
return path.join(home, 'Library', 'Application Support', APP_NAME);
|
|
24
|
+
}
|
|
25
|
+
const base = env.XDG_DATA_HOME || path.join(home, '.local', 'share');
|
|
26
|
+
return path.join(base, APP_NAME);
|
|
27
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* npx @jagilber-org/index-server --setup
|
|
16
16
|
* npm run setup
|
|
17
17
|
* node scripts/build/setup-wizard.mjs
|
|
18
|
-
* node scripts/build/setup-wizard.mjs --non-interactive --profile enhanced --root C
|
|
18
|
+
* node scripts/build/setup-wizard.mjs --non-interactive --profile enhanced --root C:/.tools/index-server
|
|
19
19
|
*/
|
|
20
20
|
import fs from 'fs';
|
|
21
21
|
import path from 'path';
|
|
@@ -23,6 +23,7 @@ import { execFileSync } from 'child_process';
|
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
24
24
|
import { createRequire } from 'module';
|
|
25
25
|
import { select, input, confirm, checkbox } from '@inquirer/prompts';
|
|
26
|
+
import { defaultUserRoot } from './setup-wizard-paths.mjs';
|
|
26
27
|
|
|
27
28
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
29
|
const ROOT = path.resolve(__dirname, '..', '..');
|
|
@@ -33,17 +34,6 @@ function writeTextFile(filePath, content) {
|
|
|
33
34
|
}
|
|
34
35
|
const IS_WINDOWS = process.platform === 'win32';
|
|
35
36
|
|
|
36
|
-
// Default install root for non-repo installs. Lives under the user profile so
|
|
37
|
-
// neither admin/elevated rights nor a cluttered C:\ root are required, and the
|
|
38
|
-
// runtime self-deploys cleanly there (args + cwd resolve under this root).
|
|
39
|
-
function defaultUserRoot() {
|
|
40
|
-
if (IS_WINDOWS) {
|
|
41
|
-
const base = process.env.LOCALAPPDATA || process.env.APPDATA || process.env.USERPROFILE || process.cwd();
|
|
42
|
-
return path.join(base, 'index-server');
|
|
43
|
-
}
|
|
44
|
-
const home = process.env.HOME || process.cwd();
|
|
45
|
-
return path.join(home, '.local', 'share', 'index-server');
|
|
46
|
-
}
|
|
47
37
|
function parsePositiveTimeout(value, fallback) {
|
|
48
38
|
const parsed = Number(value);
|
|
49
39
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
@@ -231,11 +221,10 @@ async function runInteractiveWizard() {
|
|
|
231
221
|
default: 'default',
|
|
232
222
|
});
|
|
233
223
|
|
|
234
|
-
// Step 2: Root directory
|
|
235
|
-
const defaultRoot = defaultUserRoot();
|
|
224
|
+
// Step 2: Root directory — defaults to per-user data dir (no admin rights, no hardcoded C:\ path)
|
|
236
225
|
const root = path.resolve(await input({
|
|
237
226
|
message: 'Base directory (all data paths resolve under this root)',
|
|
238
|
-
default:
|
|
227
|
+
default: defaultUserRoot(),
|
|
239
228
|
}));
|
|
240
229
|
|
|
241
230
|
// Step 3: Server name for mcp.json entry
|
|
@@ -648,12 +637,6 @@ Non-interactive mode:
|
|
|
648
637
|
console.log(`\n✅ .env written to: ${envPath}`);
|
|
649
638
|
}
|
|
650
639
|
|
|
651
|
-
// ── Deploy runtime BEFORE config generation ─────────────────────────
|
|
652
|
-
// resolveServerLaunch picks 'local' source (cwd = config.root) only when
|
|
653
|
-
// <config.root>/dist/server/index-server.js exists. Deploy first so configs
|
|
654
|
-
// are emitted with stable user-data-root paths instead of npm-global paths.
|
|
655
|
-
await deployRuntime(config);
|
|
656
|
-
|
|
657
640
|
// ── Multi-target config generation ──────────────────────────────────
|
|
658
641
|
const configTargets = resolveConfigPaths(config);
|
|
659
642
|
|
|
@@ -711,6 +694,9 @@ Non-interactive mode:
|
|
|
711
694
|
}
|
|
712
695
|
}
|
|
713
696
|
|
|
697
|
+
// ── Deploy runtime if target root differs from package root ─────────
|
|
698
|
+
await deployRuntime(config);
|
|
699
|
+
|
|
714
700
|
// ── Next steps ──────────────────────────────────────────────────────
|
|
715
701
|
const proto = (config.profile === 'enhanced' || config.profile === 'experimental') ? 'https' : 'http';
|
|
716
702
|
const launch = resolveServerLaunch(config);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# scripts/client
|
|
2
|
+
|
|
3
|
+
Client-side CLI tools and templates for connecting to a running Index Server via
|
|
4
|
+
MCP. These are the scripts users run against a deployed server; they do not
|
|
5
|
+
require the source tree to be built.
|
|
6
|
+
|
|
7
|
+
## Scripts
|
|
8
|
+
|
|
9
|
+
| Script | Purpose |
|
|
10
|
+
|--------|---------|
|
|
11
|
+
| `index-server-client.ps1` | PowerShell MCP client: connect, call tools interactively |
|
|
12
|
+
| `index-server-client.sh` | Bash equivalent for Linux/macOS |
|
|
13
|
+
| `powershell-mcp-server.ps1` | Example PowerShell-hosted MCP server (reference implementation) |
|
|
14
|
+
| `powershell-mcp-template.ps1` | Template for building a custom PowerShell MCP server |
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```pwsh
|
|
19
|
+
# Connect to a local dev server (stdio transport)
|
|
20
|
+
pwsh -File scripts/client/index-server-client.ps1
|
|
21
|
+
|
|
22
|
+
# Connect to a remote HTTP endpoint
|
|
23
|
+
pwsh -File scripts/client/index-server-client.ps1 -Uri http://localhost:9100
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> See `docs/client_scripts.md` and `docs/powershell_mcp_guide.md` for full usage.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Index Server REST client for subagents without MCP tool access.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Provides CRUD operations against the Index Server dashboard REST bridge
|
|
7
|
+
(POST /api/tools/:name). Works with both HTTP and HTTPS endpoints.
|
|
8
|
+
Returns structured JSON to stdout for machine consumption.
|
|
9
|
+
|
|
10
|
+
.PARAMETER BaseUrl
|
|
11
|
+
Server URL, e.g. http://localhost:8787 or https://localhost:8787
|
|
12
|
+
|
|
13
|
+
.PARAMETER Action
|
|
14
|
+
One of: search, get, list, add, remove, groom, health, track, hotset
|
|
15
|
+
|
|
16
|
+
.PARAMETER Id
|
|
17
|
+
Instruction ID (for get, remove, track)
|
|
18
|
+
|
|
19
|
+
.PARAMETER Keywords
|
|
20
|
+
Search keywords array (for search)
|
|
21
|
+
|
|
22
|
+
.PARAMETER Mode
|
|
23
|
+
Search mode: keyword, regex, semantic (default: keyword)
|
|
24
|
+
|
|
25
|
+
.PARAMETER Body
|
|
26
|
+
Instruction body text (for add)
|
|
27
|
+
|
|
28
|
+
.PARAMETER Title
|
|
29
|
+
Instruction title (for add)
|
|
30
|
+
|
|
31
|
+
.PARAMETER Priority
|
|
32
|
+
Instruction priority 1-100 (for add, default: 50)
|
|
33
|
+
|
|
34
|
+
.PARAMETER Signal
|
|
35
|
+
Usage signal: helpful, not-relevant, outdated, applied (for track)
|
|
36
|
+
|
|
37
|
+
.PARAMETER Overwrite
|
|
38
|
+
Allow overwriting existing instruction (for add)
|
|
39
|
+
|
|
40
|
+
.PARAMETER DryRun
|
|
41
|
+
Preview groom changes without writing (for groom)
|
|
42
|
+
|
|
43
|
+
.PARAMETER Limit
|
|
44
|
+
Max results (for search, list, hotset)
|
|
45
|
+
|
|
46
|
+
.PARAMETER ExpectId
|
|
47
|
+
Optional ID to prioritize in list results when validating CRUD flows
|
|
48
|
+
|
|
49
|
+
.PARAMETER SkipCertCheck
|
|
50
|
+
Skip TLS certificate validation (self-signed certs)
|
|
51
|
+
|
|
52
|
+
.EXAMPLE
|
|
53
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action health
|
|
54
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action search -Keywords deploy,release
|
|
55
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action get -Id my-instruction-id
|
|
56
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action list -Limit 20
|
|
57
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action add -Id new-inst -Title "My Instruction" -Body "Content here"
|
|
58
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action remove -Id old-inst
|
|
59
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action track -Id some-inst -Signal helpful
|
|
60
|
+
.\index-server-client.ps1 -BaseUrl http://localhost:8787 -Action groom -DryRun
|
|
61
|
+
.\index-server-client.ps1 -BaseUrl https://localhost:8787 -Action health -SkipCertCheck
|
|
62
|
+
#>
|
|
63
|
+
[CmdletBinding()]
|
|
64
|
+
param(
|
|
65
|
+
[string]$BaseUrl = $env:INDEX_SERVER_URL,
|
|
66
|
+
[Parameter(Mandatory)]
|
|
67
|
+
[ValidateSet('search','get','list','add','remove','groom','health','track','hotset')]
|
|
68
|
+
[string]$Action,
|
|
69
|
+
[string]$Id,
|
|
70
|
+
[string[]]$Keywords,
|
|
71
|
+
[ValidateSet('keyword','regex','semantic')]
|
|
72
|
+
[string]$Mode = 'keyword',
|
|
73
|
+
[string]$Body,
|
|
74
|
+
[string]$Title,
|
|
75
|
+
[int]$Priority = 50,
|
|
76
|
+
[ValidateSet('helpful','not-relevant','outdated','applied')]
|
|
77
|
+
[string]$Signal,
|
|
78
|
+
[switch]$Overwrite,
|
|
79
|
+
[switch]$DryRun,
|
|
80
|
+
[int]$Limit = 50,
|
|
81
|
+
[string]$ExpectId,
|
|
82
|
+
[switch]$SkipCertCheck,
|
|
83
|
+
[string]$AdminKey = $env:INDEX_SERVER_ADMIN_API_KEY
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
$ErrorActionPreference = 'Stop'
|
|
87
|
+
if (-not $BaseUrl) {
|
|
88
|
+
$BaseUrl = 'http://localhost:8787'
|
|
89
|
+
}
|
|
90
|
+
$BaseUrl = $BaseUrl.TrimEnd('/')
|
|
91
|
+
|
|
92
|
+
function Invoke-Tool {
|
|
93
|
+
param([string]$Tool, [hashtable]$Params)
|
|
94
|
+
$uri = "$BaseUrl/api/tools/$Tool"
|
|
95
|
+
$jsonBody = $Params | ConvertTo-Json -Depth 10 -Compress
|
|
96
|
+
$splat = @{
|
|
97
|
+
Uri = $uri
|
|
98
|
+
Method = 'POST'
|
|
99
|
+
ContentType = 'application/json'
|
|
100
|
+
Body = $jsonBody
|
|
101
|
+
}
|
|
102
|
+
if ($AdminKey) {
|
|
103
|
+
$splat.Headers = @{ Authorization = "Bearer $AdminKey" }
|
|
104
|
+
}
|
|
105
|
+
if ($SkipCertCheck) {
|
|
106
|
+
if ($PSVersionTable.PSVersion.Major -ge 7) {
|
|
107
|
+
$splat.SkipCertificateCheck = $true
|
|
108
|
+
} else {
|
|
109
|
+
# PS 5.1 workaround
|
|
110
|
+
if (-not ([System.Management.Automation.PSTypeName]'TrustAll').Type) {
|
|
111
|
+
Add-Type @"
|
|
112
|
+
using System.Net;
|
|
113
|
+
using System.Net.Security;
|
|
114
|
+
using System.Security.Cryptography.X509Certificates;
|
|
115
|
+
public class TrustAll {
|
|
116
|
+
public static void Enable() {
|
|
117
|
+
ServicePointManager.ServerCertificateValidationCallback =
|
|
118
|
+
delegate { return true; };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
"@
|
|
122
|
+
}
|
|
123
|
+
[TrustAll]::Enable()
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
$resp = Invoke-RestMethod @splat
|
|
128
|
+
return @{ success = $true; result = $resp }
|
|
129
|
+
} catch {
|
|
130
|
+
$msg = $_.Exception.Message
|
|
131
|
+
$status = $null
|
|
132
|
+
if ($_.Exception.Response) {
|
|
133
|
+
$status = [int]$_.Exception.Response.StatusCode
|
|
134
|
+
try {
|
|
135
|
+
$reader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
|
|
136
|
+
$errBody = $reader.ReadToEnd() | ConvertFrom-Json
|
|
137
|
+
$msg = $errBody.error
|
|
138
|
+
} catch { }
|
|
139
|
+
}
|
|
140
|
+
return @{ success = $false; error = $msg; status = $status }
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
$output = switch ($Action) {
|
|
145
|
+
'health' {
|
|
146
|
+
Invoke-Tool 'health_check' @{}
|
|
147
|
+
}
|
|
148
|
+
'search' {
|
|
149
|
+
if (-not $Keywords -or $Keywords.Count -eq 0) {
|
|
150
|
+
@{ success = $false; error = 'Keywords required for search' }
|
|
151
|
+
} else {
|
|
152
|
+
Invoke-Tool 'index_search' @{ keywords = $Keywords; mode = $Mode; limit = $Limit }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
'get' {
|
|
156
|
+
if (-not $Id) { @{ success = $false; error = 'Id required for get' } }
|
|
157
|
+
else { Invoke-Tool 'index_dispatch' @{ action = 'get'; id = $Id } }
|
|
158
|
+
}
|
|
159
|
+
'list' {
|
|
160
|
+
$p = @{ action = 'list'; limit = $Limit }
|
|
161
|
+
if ($ExpectId) { $p.expectId = $ExpectId }
|
|
162
|
+
Invoke-Tool 'index_dispatch' $p
|
|
163
|
+
}
|
|
164
|
+
'add' {
|
|
165
|
+
if (-not $Id) { @{ success = $false; error = 'Id required for add' } }
|
|
166
|
+
elseif (-not $Body) { @{ success = $false; error = 'Body required for add' } }
|
|
167
|
+
else {
|
|
168
|
+
$entry = @{
|
|
169
|
+
id = $Id
|
|
170
|
+
title = if ($Title) { $Title } else { $Id }
|
|
171
|
+
body = $Body
|
|
172
|
+
priority = $Priority
|
|
173
|
+
audience = 'all'
|
|
174
|
+
requirement = 'optional'
|
|
175
|
+
categories = @('general')
|
|
176
|
+
contentType = 'instruction'
|
|
177
|
+
}
|
|
178
|
+
$params = @{ entry = $entry; lax = $true }
|
|
179
|
+
if ($Overwrite) { $params.overwrite = $true }
|
|
180
|
+
Invoke-Tool 'index_add' $params
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
'remove' {
|
|
184
|
+
if (-not $Id) { @{ success = $false; error = 'Id required for remove' } }
|
|
185
|
+
else { Invoke-Tool 'index_remove' @{ ids = @($Id) } }
|
|
186
|
+
}
|
|
187
|
+
'track' {
|
|
188
|
+
if (-not $Id) { @{ success = $false; error = 'Id required for track' } }
|
|
189
|
+
else {
|
|
190
|
+
$p = @{ id = $Id }
|
|
191
|
+
if ($Signal) { $p.signal = $Signal }
|
|
192
|
+
Invoke-Tool 'usage_track' $p
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
'hotset' {
|
|
196
|
+
Invoke-Tool 'usage_hotset' @{ limit = $Limit }
|
|
197
|
+
}
|
|
198
|
+
'groom' {
|
|
199
|
+
Invoke-Tool 'index_groom' @{ mode = @{ dryRun = [bool]$DryRun } }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
$output | ConvertTo-Json -Depth 10
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# index-server-client.sh -- Index Server REST client for subagents without MCP tool access
|
|
3
|
+
# Provides CRUD operations via the dashboard REST bridge (POST /api/tools/:name)
|
|
4
|
+
# Works with both HTTP and HTTPS. Returns structured JSON to stdout.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ./index-server-client.sh health
|
|
8
|
+
# ./index-server-client.sh search "deploy release" [keyword|regex|semantic] [limit]
|
|
9
|
+
# ./index-server-client.sh get <id>
|
|
10
|
+
# ./index-server-client.sh list [limit]
|
|
11
|
+
# ./index-server-client.sh add <id> <title> <body> [priority] [--overwrite]
|
|
12
|
+
# ./index-server-client.sh remove <id>
|
|
13
|
+
# ./index-server-client.sh track <id> [helpful|not-relevant|outdated|applied]
|
|
14
|
+
# ./index-server-client.sh hotset [limit]
|
|
15
|
+
# ./index-server-client.sh groom [--dry-run]
|
|
16
|
+
#
|
|
17
|
+
# Env: INDEX_SERVER_URL (default: http://localhost:8787)
|
|
18
|
+
# INDEX_SERVER_ADMIN_API_KEY to authenticate with Bearer token
|
|
19
|
+
# INDEX_SERVER_SKIP_CERT=1 to skip TLS cert validation (self-signed)
|
|
20
|
+
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
BASE_URL="${INDEX_SERVER_URL:-http://localhost:8787}"
|
|
24
|
+
BASE_URL="${BASE_URL%/}"
|
|
25
|
+
ADMIN_KEY="${INDEX_SERVER_ADMIN_API_KEY:-}"
|
|
26
|
+
|
|
27
|
+
CURL_OPTS=(-s -S --fail-with-body -H "Content-Type: application/json")
|
|
28
|
+
if [ -n "$ADMIN_KEY" ]; then
|
|
29
|
+
CURL_OPTS+=(-H "Authorization: Bearer ${ADMIN_KEY}")
|
|
30
|
+
fi
|
|
31
|
+
if [ "${INDEX_SERVER_SKIP_CERT:-}" = "1" ]; then
|
|
32
|
+
CURL_OPTS+=(-k)
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
call_tool() {
|
|
36
|
+
local tool="$1"
|
|
37
|
+
local body="$2"
|
|
38
|
+
local url="${BASE_URL}/api/tools/${tool}"
|
|
39
|
+
local http_code resp
|
|
40
|
+
resp=$(curl "${CURL_OPTS[@]}" -w "\n%{http_code}" -X POST -d "$body" "$url" 2>&1) || true
|
|
41
|
+
http_code=$(echo "$resp" | tail -1)
|
|
42
|
+
local json_body
|
|
43
|
+
json_body=$(echo "$resp" | sed '$d')
|
|
44
|
+
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ] 2>/dev/null; then
|
|
45
|
+
echo "{\"success\":true,\"status\":${http_code},\"result\":${json_body:-null}}"
|
|
46
|
+
else
|
|
47
|
+
echo "{\"success\":false,\"status\":${http_code:-0},\"error\":${json_body:-\"request failed\"}}"
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ACTION="${1:-}"
|
|
52
|
+
shift || true
|
|
53
|
+
|
|
54
|
+
case "$ACTION" in
|
|
55
|
+
health)
|
|
56
|
+
call_tool "health_check" "{}"
|
|
57
|
+
;;
|
|
58
|
+
search)
|
|
59
|
+
terms="${1:-}"
|
|
60
|
+
mode="${2:-keyword}"
|
|
61
|
+
limit="${3:-50}"
|
|
62
|
+
if [ -z "$terms" ]; then
|
|
63
|
+
echo '{"success":false,"error":"keywords required for search"}'
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
# Convert space-separated terms to JSON array
|
|
67
|
+
kw_json=$(echo "$terms" | tr ' ' '\n' | sed 's/.*/"&"/' | paste -sd, | sed 's/^/[/;s/$/]/')
|
|
68
|
+
call_tool "index_search" "{\"keywords\":${kw_json},\"mode\":\"${mode}\",\"limit\":${limit}}"
|
|
69
|
+
;;
|
|
70
|
+
get)
|
|
71
|
+
id="${1:-}"
|
|
72
|
+
if [ -z "$id" ]; then
|
|
73
|
+
echo '{"success":false,"error":"id required for get"}'
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
call_tool "index_dispatch" "{\"action\":\"get\",\"id\":\"${id}\"}"
|
|
77
|
+
;;
|
|
78
|
+
list)
|
|
79
|
+
limit="${1:-50}"
|
|
80
|
+
call_tool "index_dispatch" "{\"action\":\"list\",\"limit\":${limit}}"
|
|
81
|
+
;;
|
|
82
|
+
add)
|
|
83
|
+
id="${1:-}"
|
|
84
|
+
title="${2:-}"
|
|
85
|
+
body="${3:-}"
|
|
86
|
+
priority="${4:-50}"
|
|
87
|
+
overwrite="false"
|
|
88
|
+
for arg in "$@"; do [ "$arg" = "--overwrite" ] && overwrite="true"; done
|
|
89
|
+
if [ -z "$id" ] || [ -z "$body" ]; then
|
|
90
|
+
echo '{"success":false,"error":"id and body required for add"}'
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
[ -z "$title" ] && title="$id"
|
|
94
|
+
# Escape body for JSON (newlines, quotes, backslashes)
|
|
95
|
+
esc_body=$(printf '%s' "$body" | python3 -c 'import json,sys;print(json.dumps(sys.stdin.read()))' 2>/dev/null || printf '%s' "$body" | sed 's/\\/\\\\/g;s/"/\\"/g' | tr '\n' ' ')
|
|
96
|
+
esc_title=$(printf '%s' "$title" | sed 's/\\/\\\\/g;s/"/\\"/g')
|
|
97
|
+
call_tool "index_add" "{\"entry\":{\"id\":\"${id}\",\"title\":\"${esc_title}\",\"body\":${esc_body},\"priority\":${priority},\"audience\":\"all\",\"requirement\":\"optional\",\"categories\":[\"general\"],\"contentType\":\"instruction\"},\"lax\":true,\"overwrite\":${overwrite}}"
|
|
98
|
+
;;
|
|
99
|
+
remove)
|
|
100
|
+
id="${1:-}"
|
|
101
|
+
if [ -z "$id" ]; then
|
|
102
|
+
echo '{"success":false,"error":"id required for remove"}'
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
call_tool "index_remove" "{\"ids\":[\"${id}\"]}"
|
|
106
|
+
;;
|
|
107
|
+
track)
|
|
108
|
+
id="${1:-}"
|
|
109
|
+
signal="${2:-}"
|
|
110
|
+
if [ -z "$id" ]; then
|
|
111
|
+
echo '{"success":false,"error":"id required for track"}'
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
if [ -n "$signal" ]; then
|
|
115
|
+
call_tool "usage_track" "{\"id\":\"${id}\",\"signal\":\"${signal}\"}"
|
|
116
|
+
else
|
|
117
|
+
call_tool "usage_track" "{\"id\":\"${id}\"}"
|
|
118
|
+
fi
|
|
119
|
+
;;
|
|
120
|
+
hotset)
|
|
121
|
+
limit="${1:-10}"
|
|
122
|
+
call_tool "usage_hotset" "{\"limit\":${limit}}"
|
|
123
|
+
;;
|
|
124
|
+
groom)
|
|
125
|
+
dry="false"
|
|
126
|
+
for arg in "$@"; do [ "$arg" = "--dry-run" ] && dry="true"; done
|
|
127
|
+
call_tool "index_groom" "{\"mode\":{\"dryRun\":${dry}}}"
|
|
128
|
+
;;
|
|
129
|
+
*)
|
|
130
|
+
cat <<'EOF'
|
|
131
|
+
{"success":false,"error":"unknown action","usage":{
|
|
132
|
+
"actions":["health","search","get","list","add","remove","track","hotset","groom"],
|
|
133
|
+
"examples":[
|
|
134
|
+
"index-server-client.sh health",
|
|
135
|
+
"index-server-client.sh search 'deploy release' semantic 10",
|
|
136
|
+
"index-server-client.sh get my-instruction-id",
|
|
137
|
+
"index-server-client.sh list 20",
|
|
138
|
+
"index-server-client.sh add my-id 'My Title' 'Body content' 50",
|
|
139
|
+
"index-server-client.sh remove my-id",
|
|
140
|
+
"index-server-client.sh track my-id helpful",
|
|
141
|
+
"index-server-client.sh hotset 10",
|
|
142
|
+
"index-server-client.sh groom --dry-run"
|
|
143
|
+
],
|
|
144
|
+
"env":["INDEX_SERVER_URL=http://localhost:8787","INDEX_SERVER_SKIP_CERT=1"]
|
|
145
|
+
}}
|
|
146
|
+
EOF
|
|
147
|
+
exit 1
|
|
148
|
+
;;
|
|
149
|
+
esac
|