@oh-my-pi/pi-coding-agent 17.2.0 → 17.2.1
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 +18 -0
- package/dist/{CHANGELOG-be1f2t8h.md → CHANGELOG-dj46zzrm.md} +18 -0
- package/dist/cli.js +3340 -3195
- package/dist/types/config/model-discovery.d.ts +12 -0
- package/dist/types/config/settings-schema.d.ts +10 -0
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +23 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/security-protocol.d.ts +15 -0
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/sdk.d.ts +17 -0
- package/dist/types/security/auth.d.ts +30 -0
- package/dist/types/security/cloud.d.ts +79 -0
- package/dist/types/security/comparison.d.ts +49 -0
- package/dist/types/security/contracts/ids.d.ts +15 -0
- package/dist/types/security/contracts/index.d.ts +4 -0
- package/dist/types/security/contracts/schemas.d.ts +660 -0
- package/dist/types/security/contracts/types.d.ts +234 -0
- package/dist/types/security/contracts/validation.d.ts +5 -0
- package/dist/types/security/coordinator.d.ts +100 -0
- package/dist/types/security/importers/codex-security.d.ts +7 -0
- package/dist/types/security/importers/index.d.ts +2 -0
- package/dist/types/security/importers/sarif.d.ts +9 -0
- package/dist/types/security/index.d.ts +13 -0
- package/dist/types/security/preflight.d.ts +61 -0
- package/dist/types/security/provenance.d.ts +24 -0
- package/dist/types/security/publication.d.ts +78 -0
- package/dist/types/security/remediation.d.ts +27 -0
- package/dist/types/security/resource-output.d.ts +8 -0
- package/dist/types/security/sarif.d.ts +2 -0
- package/dist/types/security/store.d.ts +40 -0
- package/dist/types/slash-commands/helpers/security.d.ts +2 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/index.d.ts +6 -1
- package/dist/types/tools/security-scan.d.ts +96 -0
- package/package.json +12 -12
- package/scripts/security-compare.ts +40 -0
- package/src/config/model-discovery.ts +32 -5
- package/src/config/model-registry.ts +4 -0
- package/src/config/settings-schema.ts +12 -0
- package/src/eval/py/prelude.py +7 -3
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +53 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/router.ts +4 -1
- package/src/internal-urls/security-protocol.ts +261 -0
- package/src/internal-urls/types.ts +1 -1
- package/src/lsp/index.ts +3 -0
- package/src/modes/rpc/host-uris.ts +6 -0
- package/src/prompts/agents/security-reviewer.md +75 -0
- package/src/prompts/security/scan-coordinator.md +7 -0
- package/src/prompts/security/scan-request.md +21 -0
- package/src/prompts/security/validate-request.md +8 -0
- package/src/prompts/system/system-prompt.md +3 -0
- package/src/prompts/tools/security-publish.md +1 -0
- package/src/prompts/tools/security-scan.md +1 -0
- package/src/sdk.ts +34 -6
- package/src/security/auth.ts +98 -0
- package/src/security/cloud.ts +686 -0
- package/src/security/comparison.ts +255 -0
- package/src/security/contracts/ids.ts +111 -0
- package/src/security/contracts/index.ts +4 -0
- package/src/security/contracts/schemas.ts +201 -0
- package/src/security/contracts/types.ts +254 -0
- package/src/security/contracts/validation.ts +65 -0
- package/src/security/coordinator.ts +708 -0
- package/src/security/importers/codex-security.ts +387 -0
- package/src/security/importers/index.ts +2 -0
- package/src/security/importers/sarif.ts +357 -0
- package/src/security/index.ts +13 -0
- package/src/security/preflight.ts +405 -0
- package/src/security/provenance.ts +106 -0
- package/src/security/publication.ts +326 -0
- package/src/security/remediation.ts +93 -0
- package/src/security/resource-output.ts +50 -0
- package/src/security/sarif.ts +78 -0
- package/src/security/store.ts +430 -0
- package/src/slash-commands/builtin-registry.ts +21 -0
- package/src/slash-commands/helpers/security.ts +451 -0
- package/src/system-prompt.ts +4 -0
- package/src/task/agents.ts +2 -0
- package/src/task/executor.ts +3 -0
- package/src/task/structured-subagent.ts +6 -4
- package/src/tools/builtin-names.ts +1 -0
- package/src/tools/index.ts +9 -1
- package/src/tools/path-utils.ts +3 -0
- package/src/tools/security-scan.ts +287 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Clipboard, InMemorySnapshotStore } from "@oh-my-pi/hashline";
|
|
2
|
-
import type { AgentTelemetryConfig, AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { AgentOptions, AgentTelemetryConfig, AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
3
3
|
import type { FetchImpl, ImageContent, Model, ServiceTierByFamily, ToolChoice } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import type { AsyncJobManager } from "../async/job-manager.js";
|
|
5
5
|
import type { Rule } from "../capability/rule.js";
|
|
@@ -65,6 +65,7 @@ export * from "./read.js";
|
|
|
65
65
|
export * from "./report-tool-issue.js";
|
|
66
66
|
export * from "./resolve.js";
|
|
67
67
|
export * from "./review.js";
|
|
68
|
+
export * from "./security-scan.js";
|
|
68
69
|
export * from "./todo.js";
|
|
69
70
|
export * from "./tts.js";
|
|
70
71
|
export * from "./vibe.js";
|
|
@@ -123,6 +124,8 @@ export interface ToolSession {
|
|
|
123
124
|
suppressSpawnAdvisory?: boolean;
|
|
124
125
|
/** Optional fetch implementation injected into the URL read pipeline (tests, proxies). Defaults to global fetch. */
|
|
125
126
|
fetch?: FetchImpl;
|
|
127
|
+
/** Provider credential resolver forwarded unchanged to restricted child sessions. */
|
|
128
|
+
getApiKey?: AgentOptions["getApiKey"];
|
|
126
129
|
/** Skip subprocess-kernel availability checks and warmup */
|
|
127
130
|
skipPythonPreflight?: boolean;
|
|
128
131
|
/** Pre-loaded context files (AGENTS.md, etc) */
|
|
@@ -152,6 +155,8 @@ export interface ToolSession {
|
|
|
152
155
|
customToolPaths?: ToolPathWithSource[];
|
|
153
156
|
/** Whether LSP integrations are enabled */
|
|
154
157
|
enableLsp?: boolean;
|
|
158
|
+
/** Whether LSP is limited to navigation and diagnostics. */
|
|
159
|
+
lspReadOnly?: boolean;
|
|
155
160
|
/** Whether this invocation may expose IRC. `false` removes it even for subagents. */
|
|
156
161
|
enableIrc?: boolean;
|
|
157
162
|
/**
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { AgentTool, AgentToolResult, ToolTier } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import { type CodexSecurityCloudConfiguration, type CodexSecurityCloudStats } from "../security/cloud.js";
|
|
3
|
+
import { type SecurityValidationStatus } from "../security/contracts/index.js";
|
|
4
|
+
import type { SecurityOperationSnapshot } from "../security/coordinator.js";
|
|
5
|
+
import type { ToolSession } from "./index.js";
|
|
6
|
+
declare const securityScanSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
7
|
+
action: "cancel" | "cloud_pull" | "cloud_scans" | "cloud_start" | "cloud_status" | "preflight" | "start" | "status" | "validate";
|
|
8
|
+
plan_id?: string | undefined;
|
|
9
|
+
operation_id?: string | undefined;
|
|
10
|
+
target_kind?: "ref_diff" | "repository" | "scoped_path" | "working_tree" | undefined;
|
|
11
|
+
include_paths?: string[] | undefined;
|
|
12
|
+
exclude_paths?: string[] | undefined;
|
|
13
|
+
base_revision?: string | undefined;
|
|
14
|
+
head_revision?: string | undefined;
|
|
15
|
+
knowledge_base_paths?: string[] | undefined;
|
|
16
|
+
output_root?: string | undefined;
|
|
17
|
+
archive_existing?: boolean | undefined;
|
|
18
|
+
credential_id?: number | undefined;
|
|
19
|
+
scan_id?: string | undefined;
|
|
20
|
+
finding_id?: string | undefined;
|
|
21
|
+
validation_status?: "error" | "partial" | "rejected" | "unvalidated" | "validated" | undefined;
|
|
22
|
+
validation_summary?: string | undefined;
|
|
23
|
+
validation_evidence?: {
|
|
24
|
+
label: string;
|
|
25
|
+
explanation: string;
|
|
26
|
+
}[] | undefined;
|
|
27
|
+
cloud_configuration_id?: string | undefined;
|
|
28
|
+
repository_id?: string | undefined;
|
|
29
|
+
repository_url?: string | undefined;
|
|
30
|
+
environment_id?: string | undefined;
|
|
31
|
+
lookback_days?: number | "all" | undefined;
|
|
32
|
+
}, {}>;
|
|
33
|
+
type SecurityScanParams = typeof securityScanSchema.infer;
|
|
34
|
+
export interface SecurityScanToolDetails {
|
|
35
|
+
action: SecurityScanParams["action"];
|
|
36
|
+
plan?: {
|
|
37
|
+
id: string;
|
|
38
|
+
fingerprint: string;
|
|
39
|
+
};
|
|
40
|
+
operation?: SecurityOperationSnapshot;
|
|
41
|
+
cancelled?: boolean;
|
|
42
|
+
finding?: {
|
|
43
|
+
id: string;
|
|
44
|
+
validationStatus: SecurityValidationStatus;
|
|
45
|
+
};
|
|
46
|
+
cloudConfigurations?: CodexSecurityCloudConfiguration[];
|
|
47
|
+
cloudStats?: CodexSecurityCloudStats;
|
|
48
|
+
cloudScan?: {
|
|
49
|
+
id: string;
|
|
50
|
+
repositoryUrl: string;
|
|
51
|
+
};
|
|
52
|
+
importedScan?: {
|
|
53
|
+
id: string;
|
|
54
|
+
findingCount: number;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export declare class SecurityScanTool implements AgentTool<typeof securityScanSchema, SecurityScanToolDetails> {
|
|
58
|
+
readonly session: ToolSession;
|
|
59
|
+
readonly name = "security_scan";
|
|
60
|
+
readonly approval: ToolTier;
|
|
61
|
+
readonly label = "Security Scan";
|
|
62
|
+
readonly loadMode = "discoverable";
|
|
63
|
+
readonly summary = "Run OMP-native scans and explicit Codex Security cloud operations";
|
|
64
|
+
readonly description: string;
|
|
65
|
+
readonly parameters: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
66
|
+
action: "cancel" | "cloud_pull" | "cloud_scans" | "cloud_start" | "cloud_status" | "preflight" | "start" | "status" | "validate";
|
|
67
|
+
plan_id?: string | undefined;
|
|
68
|
+
operation_id?: string | undefined;
|
|
69
|
+
target_kind?: "ref_diff" | "repository" | "scoped_path" | "working_tree" | undefined;
|
|
70
|
+
include_paths?: string[] | undefined;
|
|
71
|
+
exclude_paths?: string[] | undefined;
|
|
72
|
+
base_revision?: string | undefined;
|
|
73
|
+
head_revision?: string | undefined;
|
|
74
|
+
knowledge_base_paths?: string[] | undefined;
|
|
75
|
+
output_root?: string | undefined;
|
|
76
|
+
archive_existing?: boolean | undefined;
|
|
77
|
+
credential_id?: number | undefined;
|
|
78
|
+
scan_id?: string | undefined;
|
|
79
|
+
finding_id?: string | undefined;
|
|
80
|
+
validation_status?: "error" | "partial" | "rejected" | "unvalidated" | "validated" | undefined;
|
|
81
|
+
validation_summary?: string | undefined;
|
|
82
|
+
validation_evidence?: {
|
|
83
|
+
label: string;
|
|
84
|
+
explanation: string;
|
|
85
|
+
}[] | undefined;
|
|
86
|
+
cloud_configuration_id?: string | undefined;
|
|
87
|
+
repository_id?: string | undefined;
|
|
88
|
+
repository_url?: string | undefined;
|
|
89
|
+
environment_id?: string | undefined;
|
|
90
|
+
lookback_days?: number | "all" | undefined;
|
|
91
|
+
}, {}>;
|
|
92
|
+
readonly strict = true;
|
|
93
|
+
constructor(session: ToolSession);
|
|
94
|
+
execute(_toolCallId: string, params: SecurityScanParams, signal?: AbortSignal): Promise<AgentToolResult<SecurityScanToolDetails>>;
|
|
95
|
+
}
|
|
96
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "17.2.
|
|
4
|
+
"version": "17.2.1",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -52,17 +52,17 @@
|
|
|
52
52
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
53
53
|
"@babel/parser": "^7.29.7",
|
|
54
54
|
"@mozilla/readability": "^0.6.0",
|
|
55
|
-
"@oh-my-pi/hashline": "17.2.
|
|
56
|
-
"@oh-my-pi/omp-stats": "17.2.
|
|
57
|
-
"@oh-my-pi/pi-agent-core": "17.2.
|
|
58
|
-
"@oh-my-pi/pi-ai": "17.2.
|
|
59
|
-
"@oh-my-pi/pi-catalog": "17.2.
|
|
60
|
-
"@oh-my-pi/pi-mnemopi": "17.2.
|
|
61
|
-
"@oh-my-pi/pi-natives": "17.2.
|
|
62
|
-
"@oh-my-pi/pi-tui": "17.2.
|
|
63
|
-
"@oh-my-pi/pi-utils": "17.2.
|
|
64
|
-
"@oh-my-pi/pi-wire": "17.2.
|
|
65
|
-
"@oh-my-pi/snapcompact": "17.2.
|
|
55
|
+
"@oh-my-pi/hashline": "17.2.1",
|
|
56
|
+
"@oh-my-pi/omp-stats": "17.2.1",
|
|
57
|
+
"@oh-my-pi/pi-agent-core": "17.2.1",
|
|
58
|
+
"@oh-my-pi/pi-ai": "17.2.1",
|
|
59
|
+
"@oh-my-pi/pi-catalog": "17.2.1",
|
|
60
|
+
"@oh-my-pi/pi-mnemopi": "17.2.1",
|
|
61
|
+
"@oh-my-pi/pi-natives": "17.2.1",
|
|
62
|
+
"@oh-my-pi/pi-tui": "17.2.1",
|
|
63
|
+
"@oh-my-pi/pi-utils": "17.2.1",
|
|
64
|
+
"@oh-my-pi/pi-wire": "17.2.1",
|
|
65
|
+
"@oh-my-pi/snapcompact": "17.2.1",
|
|
66
66
|
"@opentelemetry/api": "^1.9.1",
|
|
67
67
|
"@opentelemetry/api-logs": "^0.220.0",
|
|
68
68
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { isEnoent } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import { compareSecurityProducers, importCodexSecurityBundle, parseSecurityScanBundle } from "../src/security";
|
|
5
|
+
|
|
6
|
+
async function readBundle(directory: string) {
|
|
7
|
+
const root = path.resolve(directory);
|
|
8
|
+
let scan: unknown;
|
|
9
|
+
try {
|
|
10
|
+
scan = JSON.parse(await Bun.file(path.join(root, "scan.json")).text()) as unknown;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (!isEnoent(error)) throw error;
|
|
13
|
+
return importCodexSecurityBundle(root, { repositoryRoot: root });
|
|
14
|
+
}
|
|
15
|
+
const findings = JSON.parse(await Bun.file(path.join(root, "findings.json")).text()) as unknown;
|
|
16
|
+
const report = await Bun.file(path.join(root, "report.md"))
|
|
17
|
+
.text()
|
|
18
|
+
.catch(() => undefined);
|
|
19
|
+
const sarifText = await Bun.file(path.join(root, "results.sarif"))
|
|
20
|
+
.text()
|
|
21
|
+
.catch(() => undefined);
|
|
22
|
+
return parseSecurityScanBundle({
|
|
23
|
+
scan,
|
|
24
|
+
findings,
|
|
25
|
+
report,
|
|
26
|
+
sarif: sarifText ? (JSON.parse(sarifText) as Record<string, unknown>) : undefined,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const [referenceDirectory, candidateDirectory, outputPath] = process.argv.slice(2);
|
|
31
|
+
if (!referenceDirectory || !candidateDirectory) {
|
|
32
|
+
process.stderr.write(
|
|
33
|
+
"Usage: bun scripts/security-compare.ts <reference-scan-dir> <candidate-scan-dir> [output.json]\n",
|
|
34
|
+
);
|
|
35
|
+
process.exit(2);
|
|
36
|
+
}
|
|
37
|
+
const report = compareSecurityProducers(await readBundle(referenceDirectory), await readBundle(candidateDirectory));
|
|
38
|
+
const serialized = `${JSON.stringify(report, null, 2)}\n`;
|
|
39
|
+
if (outputPath) await Bun.write(path.resolve(outputPath), serialized);
|
|
40
|
+
else process.stdout.write(serialized);
|
|
@@ -62,6 +62,33 @@ async function withTimeoutSignal<T>(timeoutMs: number, fn: (signal: AbortSignal)
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/** Generous discovery budget for a non-loopback (remote / LAN) inference host. */
|
|
66
|
+
const REMOTE_DISCOVERY_TIMEOUT_MS = 10_000;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Pick a discovery-probe timeout for a local-engine base URL.
|
|
70
|
+
*
|
|
71
|
+
* The implicit `127.0.0.1` default probe keeps a tight `loopbackMs` cap so a
|
|
72
|
+
* busy or foreign service on the default port never stalls startup. But that
|
|
73
|
+
* cap is far too short for a host reached over the network: a user who points
|
|
74
|
+
* `LLAMA_CPP_BASE_URL` / `OLLAMA_BASE_URL` / `OLLAMA_HOST` at a remote or LAN
|
|
75
|
+
* machine has real round-trip latency, and a 250ms cap made that server look
|
|
76
|
+
* empty (issue #7087). Anything that is not strictly loopback therefore gets
|
|
77
|
+
* {@link REMOTE_DISCOVERY_TIMEOUT_MS}.
|
|
78
|
+
*/
|
|
79
|
+
export function discoveryProbeTimeoutMs(baseUrl: string, loopbackMs: number): number {
|
|
80
|
+
let hostname: string;
|
|
81
|
+
try {
|
|
82
|
+
hostname = new URL(baseUrl).hostname;
|
|
83
|
+
} catch {
|
|
84
|
+
return loopbackMs;
|
|
85
|
+
}
|
|
86
|
+
hostname = hostname.replace(/^\[/, "").replace(/\]$/, "");
|
|
87
|
+
const isLoopback =
|
|
88
|
+
hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::1" || /^127\./.test(hostname);
|
|
89
|
+
return isLoopback ? loopbackMs : REMOTE_DISCOVERY_TIMEOUT_MS;
|
|
90
|
+
}
|
|
91
|
+
|
|
65
92
|
const DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434";
|
|
66
93
|
const OLLAMA_HOST_DEFAULT_PORT = "11434";
|
|
67
94
|
|
|
@@ -391,7 +418,7 @@ async function discoverOllamaModelMetadata(
|
|
|
391
418
|
): Promise<OllamaDiscoveredModelMetadata | null> {
|
|
392
419
|
const showUrl = `${endpoint}/api/show`;
|
|
393
420
|
try {
|
|
394
|
-
const payload = await withTimeoutSignal(150, async signal => {
|
|
421
|
+
const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 150), async signal => {
|
|
395
422
|
const response = await ctx.fetch(showUrl, {
|
|
396
423
|
method: "POST",
|
|
397
424
|
headers: { ...(headers ?? {}), "Content-Type": "application/json" },
|
|
@@ -444,7 +471,7 @@ export async function discoverOllamaModels(
|
|
|
444
471
|
const endpoint = normalizeOllamaBaseUrl(providerConfig.baseUrl);
|
|
445
472
|
const tagsUrl = `${endpoint}/api/tags`;
|
|
446
473
|
const headers = { ...(providerConfig.headers ?? {}) };
|
|
447
|
-
const payload = await withTimeoutSignal(250, async signal => {
|
|
474
|
+
const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 250), async signal => {
|
|
448
475
|
const response = await ctx.fetch(tagsUrl, {
|
|
449
476
|
headers,
|
|
450
477
|
signal,
|
|
@@ -491,7 +518,7 @@ async function discoverLlamaCppServerMetadata(
|
|
|
491
518
|
): Promise<LlamaCppDiscoveredServerMetadata | null> {
|
|
492
519
|
const propsUrl = `${toLlamaCppNativeBaseUrl(baseUrl)}/props`;
|
|
493
520
|
try {
|
|
494
|
-
const payload = await withTimeoutSignal(150, async signal => {
|
|
521
|
+
const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 150), async signal => {
|
|
495
522
|
const response = await ctx.fetch(propsUrl, {
|
|
496
523
|
headers,
|
|
497
524
|
signal,
|
|
@@ -567,7 +594,7 @@ export async function discoverLlamaCppModels(
|
|
|
567
594
|
let headers = baseHeaders;
|
|
568
595
|
const attempt = async (h: Record<string, string>) => {
|
|
569
596
|
const [payload, metadata] = await Promise.all([
|
|
570
|
-
withTimeoutSignal(250, async signal => {
|
|
597
|
+
withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 250), async signal => {
|
|
571
598
|
const response = await ctx.fetch(modelsUrl, {
|
|
572
599
|
headers: h,
|
|
573
600
|
signal,
|
|
@@ -641,7 +668,7 @@ export async function discoverLlamaCppModelRuntimeMetadata(
|
|
|
641
668
|
const baseHeaders: Record<string, string> = { ...(model.headers ?? {}) };
|
|
642
669
|
const attempt = async (headers: Record<string, string>) => {
|
|
643
670
|
const [entries, serverMetadata] = await Promise.all([
|
|
644
|
-
withTimeoutSignal(250, async signal => {
|
|
671
|
+
withTimeoutSignal(discoveryProbeTimeoutMs(nativeBaseUrl, 250), async signal => {
|
|
645
672
|
const response = await ctx.fetch(modelsUrl, {
|
|
646
673
|
headers,
|
|
647
674
|
signal,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
openaiCodexModelManagerOptions,
|
|
28
28
|
PROVIDER_DESCRIPTORS,
|
|
29
29
|
resolveModelCacheProviderId,
|
|
30
|
+
resolveOllamaModelCacheProviderId,
|
|
30
31
|
} from "@oh-my-pi/pi-catalog/provider-models";
|
|
31
32
|
import {
|
|
32
33
|
collapseBuiltModelVariants,
|
|
@@ -1699,6 +1700,9 @@ export class ModelRegistry {
|
|
|
1699
1700
|
}
|
|
1700
1701
|
|
|
1701
1702
|
#configuredDiscoveryCacheProviderId(providerConfig: DiscoveryProviderConfig): string {
|
|
1703
|
+
if (providerConfig.discovery.type === "ollama") {
|
|
1704
|
+
return resolveOllamaModelCacheProviderId(providerConfig.provider, providerConfig.baseUrl);
|
|
1705
|
+
}
|
|
1702
1706
|
if (providerConfig.discovery.type === "openai-models-list") {
|
|
1703
1707
|
return `${providerConfig.provider}:openai-models-list-context-v2`;
|
|
1704
1708
|
}
|
|
@@ -4062,6 +4062,18 @@ export const SETTINGS_SCHEMA = {
|
|
|
4062
4062
|
},
|
|
4063
4063
|
},
|
|
4064
4064
|
|
|
4065
|
+
"security.enabled": {
|
|
4066
|
+
type: "boolean",
|
|
4067
|
+
default: false,
|
|
4068
|
+
ui: {
|
|
4069
|
+
tab: "tools",
|
|
4070
|
+
group: "Available Tools",
|
|
4071
|
+
label: "Security",
|
|
4072
|
+
description:
|
|
4073
|
+
"Enable OMP-native security scan planning, execution, and the read-only security:// resource namespace",
|
|
4074
|
+
},
|
|
4075
|
+
},
|
|
4076
|
+
|
|
4065
4077
|
"ask.enabled": {
|
|
4066
4078
|
type: "boolean",
|
|
4067
4079
|
default: true,
|
package/src/eval/py/prelude.py
CHANGED
|
@@ -376,10 +376,14 @@ if "__omp_prelude_loaded__" not in globals():
|
|
|
376
376
|
raise RuntimeError("tool bridge is unavailable in this kernel")
|
|
377
377
|
return (base.rstrip("/"), token, session)
|
|
378
378
|
|
|
379
|
+
import urllib.error, urllib.request
|
|
380
|
+
|
|
381
|
+
# urllib discovers environment and macOS SystemConfiguration proxies. This
|
|
382
|
+
# host-owned loopback endpoint must always connect directly.
|
|
383
|
+
_BRIDGE_OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
|
384
|
+
|
|
379
385
|
def _bridge_call(name: str, args: dict):
|
|
380
386
|
"""POST one request to the host tool bridge and return its `value`."""
|
|
381
|
-
import urllib.request, urllib.error
|
|
382
|
-
|
|
383
387
|
base, token, session = _tool_proxy_from_env()
|
|
384
388
|
_run_id_getter = globals().get("__omp_current_run_id__")
|
|
385
389
|
_run_id = (
|
|
@@ -400,7 +404,7 @@ if "__omp_prelude_loaded__" not in globals():
|
|
|
400
404
|
},
|
|
401
405
|
)
|
|
402
406
|
try:
|
|
403
|
-
with
|
|
407
|
+
with _BRIDGE_OPENER.open(req) as resp:
|
|
404
408
|
body = resp.read()
|
|
405
409
|
except urllib.error.HTTPError as exc:
|
|
406
410
|
body = exc.read()
|
|
@@ -140,6 +140,25 @@ export interface LsToolOptions {
|
|
|
140
140
|
operations?: LsOperations;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
export interface EditOperations {
|
|
144
|
+
readFile: (absolutePath: string) => Promise<Buffer>;
|
|
145
|
+
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
146
|
+
access: (absolutePath: string) => Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface EditToolOptions {
|
|
150
|
+
operations?: EditOperations;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface WriteOperations {
|
|
154
|
+
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
155
|
+
mkdir: (dir: string) => Promise<void>;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface WriteToolOptions {
|
|
159
|
+
operations?: WriteOperations;
|
|
160
|
+
}
|
|
161
|
+
|
|
143
162
|
const legacyBashSchema = Type.Object({
|
|
144
163
|
command: Type.String({ description: "Bash command to execute" }),
|
|
145
164
|
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds" })),
|
|
@@ -636,6 +655,40 @@ export function createLsTool(cwd: string, options?: LsToolOptions): ToolDefiniti
|
|
|
636
655
|
return createLsToolDefinition(cwd, options);
|
|
637
656
|
}
|
|
638
657
|
|
|
658
|
+
/** Create the legacy edit tool definition. */
|
|
659
|
+
export function createEditToolDefinition(cwd: string, options?: EditToolOptions): ToolDefinition {
|
|
660
|
+
if (options?.operations) {
|
|
661
|
+
throw new Error(
|
|
662
|
+
"Legacy EditToolOptions.operations is not supported: OMP's built-in edit tool writes the local " +
|
|
663
|
+
"filesystem natively and exposes no pluggable operations seam. Register a custom edit tool via " +
|
|
664
|
+
"defineTool() instead of passing operations to createEditTool()/createEditToolDefinition().",
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
return legacyBuiltinTool(cwd, "edit");
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** Create the legacy edit tool. */
|
|
671
|
+
export function createEditTool(cwd: string, options?: EditToolOptions): ToolDefinition {
|
|
672
|
+
return createEditToolDefinition(cwd, options);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/** Create the legacy write tool definition. */
|
|
676
|
+
export function createWriteToolDefinition(cwd: string, options?: WriteToolOptions): ToolDefinition {
|
|
677
|
+
if (options?.operations) {
|
|
678
|
+
throw new Error(
|
|
679
|
+
"Legacy WriteToolOptions.operations is not supported: OMP's built-in write tool writes the local " +
|
|
680
|
+
"filesystem natively and exposes no pluggable operations seam. Register a custom write tool via " +
|
|
681
|
+
"defineTool() instead of passing operations to createWriteTool()/createWriteToolDefinition().",
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
return legacyBuiltinTool(cwd, "write");
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/** Create the legacy write tool. */
|
|
688
|
+
export function createWriteTool(cwd: string, options?: WriteToolOptions): ToolDefinition {
|
|
689
|
+
return createWriteToolDefinition(cwd, options);
|
|
690
|
+
}
|
|
691
|
+
|
|
639
692
|
/** Create legacy read, bash, edit, and write tools. */
|
|
640
693
|
export function createCodingTools(cwd: string): ToolDefinition[] {
|
|
641
694
|
return LEGACY_CODING_TOOL_NAMES.map(name => legacyBuiltinTool(cwd, name));
|
|
@@ -20,6 +20,7 @@ export * from "./omp-protocol";
|
|
|
20
20
|
export * from "./parse";
|
|
21
21
|
export * from "./router";
|
|
22
22
|
export * from "./rule-protocol";
|
|
23
|
+
export * from "./security-protocol";
|
|
23
24
|
export * from "./skill-protocol";
|
|
24
25
|
export * from "./ssh-protocol";
|
|
25
26
|
export type * from "./types";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Internal URL router for internal protocols (`agent://`, `artifact://`, `history://`, `issue://`, `local://`, `mcp://`, `memory://`, `omp://`, `pr://`, `rule://`, `skill://`, `ssh://`, `vault://`, and `xd://`).
|
|
2
|
+
* Internal URL router for internal protocols (`agent://`, `artifact://`, `history://`, `issue://`, `local://`, `mcp://`, `memory://`, `omp://`, `pr://`, `rule://`, `security://`, `skill://`, `ssh://`, `vault://`, and `xd://`).
|
|
3
3
|
*
|
|
4
4
|
* One process-global router with one handler per scheme. Access via
|
|
5
5
|
* `InternalUrlRouter.instance()`. Handlers are stateless; per-session and
|
|
@@ -15,6 +15,7 @@ import { MemoryProtocolHandler } from "./memory-protocol";
|
|
|
15
15
|
import { OmpProtocolHandler } from "./omp-protocol";
|
|
16
16
|
import { extractUriScheme, parseInternalUrl } from "./parse";
|
|
17
17
|
import { RuleProtocolHandler } from "./rule-protocol";
|
|
18
|
+
import { SecurityProtocolHandler } from "./security-protocol";
|
|
18
19
|
import { SkillProtocolHandler } from "./skill-protocol";
|
|
19
20
|
import { SshProtocolHandler } from "./ssh-protocol";
|
|
20
21
|
import type {
|
|
@@ -42,6 +43,8 @@ export class InternalUrlRouter {
|
|
|
42
43
|
this.register(new VaultProtocolHandler());
|
|
43
44
|
this.register(new SkillProtocolHandler());
|
|
44
45
|
this.register(new RuleProtocolHandler());
|
|
46
|
+
// Reserved OMP-owned security-analysis namespace; vendor adapters normalize into its store.
|
|
47
|
+
this.register(new SecurityProtocolHandler());
|
|
45
48
|
this.register(new McpProtocolHandler());
|
|
46
49
|
this.register(new IssueProtocolHandler());
|
|
47
50
|
this.register(new PrProtocolHandler());
|