copilot-tap-extension 2.0.7 → 2.0.9
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 +4 -1
- package/SOUL.md +51 -0
- package/bin/install.mjs +7 -1
- package/dist/copilot-instructions.md +15 -0
- package/dist/extension.mjs +823 -29
- package/dist/skills/tap-goal/SKILL.md +13 -2
- package/dist/skills/tap-loop/SKILL.md +6 -0
- package/dist/skills/tap-monitor/SKILL.md +19 -3
- package/dist/skills/tap-orchestrate/SKILL.md +81 -0
- package/dist/version.json +1 -1
- package/docs/adr/0001-persistent-config-default-ownership.md +33 -0
- package/docs/adr/0002-local-provider-gateway-runtime-security.md +36 -0
- package/docs/adr/0003-emitter-delivery-lifecycle.md +68 -0
- package/docs/adr/0004-persistent-config-canonical-streams.md +86 -0
- package/docs/adr/0005-provider-sdk-push-and-dynamic-tools.md +48 -0
- package/docs/adr/0006-command-emitter-cwd-workspace-boundary.md +46 -0
- package/docs/adr/0007-runtime-session-workspace-context.md +62 -0
- package/docs/evals.md +41 -0
- package/docs/evolution-of-tap-icon.html +989 -0
- package/docs/providers.md +242 -0
- package/docs/recipes/adaptive-agent.md +303 -0
- package/docs/recipes/agent-brainstorm/100-extension-ideas.md +288 -0
- package/docs/recipes/agent-brainstorm/deep-ideas.md +216 -0
- package/docs/recipes/ambient-guardian.md +314 -0
- package/docs/recipes/browser-bridge.md +162 -0
- package/docs/recipes/codex-goals-for-tap-goal.md +136 -0
- package/docs/recipes/copilot-sdk-canvas.md +147 -0
- package/docs/recipes/deferred-cognition.md +310 -0
- package/docs/recipes/provider-integration-patterns.md +93 -0
- package/docs/recipes/provider-interface-advanced.md +1364 -0
- package/docs/recipes/provider-interface-core-profile.md +568 -0
- package/docs/recipes/tap-control-plane-roadmap.md +60 -0
- package/docs/recipes/universal-tool-gateway.md +202 -0
- package/docs/reference.md +229 -0
- package/docs/use-cases.md +348 -0
- package/package.json +4 -1
- package/providers/detour/README.md +84 -0
- package/providers/detour/bridge.js +219 -0
- package/providers/detour/index.mjs +322 -0
- package/providers/detour/package-lock.json +577 -0
- package/providers/detour/package.json +19 -0
- package/providers/detour/scripts/build.mjs +31 -0
- package/providers/detour/src/bridge.js +256 -0
- package/providers/detour/src/contracts.js +40 -0
- package/providers/detour/src/inspector.js +260 -0
- package/providers/detour/src/inspector.test.mjs +53 -0
- package/providers/detour/src/panel.js +465 -0
- package/providers/detour/src/provider-core.js +233 -0
- package/providers/detour/src/provider-core.test.mjs +185 -0
- package/providers/detour/src/react-context-core.js +143 -0
- package/providers/detour/src/react-context.js +44 -0
- package/providers/detour/src/react-context.test.mjs +41 -0
- package/providers/templates/README.md +23 -0
- package/providers/templates/ci-review-provider.mjs +46 -0
- package/providers/templates/detour-workflow-provider.mjs +41 -0
- package/providers/templates/jira-github-provider.mjs +42 -0
- package/providers/templates/provider-utils.mjs +45 -0
- package/providers/templates/sast-triage-provider.mjs +51 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { connectProvider, push } from "./provider-utils.mjs";
|
|
2
|
+
|
|
3
|
+
const tools = [
|
|
4
|
+
{
|
|
5
|
+
name: "ci_review_normalize_findings",
|
|
6
|
+
description: "Normalize structured code review findings into tap provider events.",
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
findings: { type: "array" },
|
|
11
|
+
runUrl: { type: "string" },
|
|
12
|
+
repository: { type: "string" }
|
|
13
|
+
},
|
|
14
|
+
required: ["findings"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
connectProvider({
|
|
20
|
+
name: "ci-review-template",
|
|
21
|
+
tools,
|
|
22
|
+
onMessage(ws, msg) {
|
|
23
|
+
if (msg.type !== "tool.call" || msg.tool !== "ci_review_normalize_findings") {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const args = msg.arguments ?? {};
|
|
27
|
+
for (const finding of args.findings ?? []) {
|
|
28
|
+
const priority = Number(finding.priority ?? 3);
|
|
29
|
+
push(ws, {
|
|
30
|
+
stream: "ci-review",
|
|
31
|
+
level: priority <= 1 ? "inject" : "surface",
|
|
32
|
+
event: {
|
|
33
|
+
type: "review.finding",
|
|
34
|
+
title: finding.title,
|
|
35
|
+
priority,
|
|
36
|
+
confidence: finding.confidence_score,
|
|
37
|
+
file: finding.code_location?.absolute_file_path,
|
|
38
|
+
line: finding.code_location?.line_range?.start,
|
|
39
|
+
runUrl: args.runUrl,
|
|
40
|
+
repository: args.repository
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
ws.send(JSON.stringify({ type: "tool.result", callId: msg.callId, result: { ok: true } }));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { connectProvider, push } from "./provider-utils.mjs";
|
|
2
|
+
|
|
3
|
+
const tools = [
|
|
4
|
+
{
|
|
5
|
+
name: "detour_emit_page_event",
|
|
6
|
+
description: "Normalize browser or Detour page events for tap streams.",
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
url: { type: "string" },
|
|
11
|
+
eventType: { type: "string" },
|
|
12
|
+
message: { type: "string" },
|
|
13
|
+
severity: { type: "string" }
|
|
14
|
+
},
|
|
15
|
+
required: ["eventType", "message"]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
connectProvider({
|
|
21
|
+
name: "detour-workflow-template",
|
|
22
|
+
tools,
|
|
23
|
+
onMessage(ws, msg) {
|
|
24
|
+
if (msg.type !== "tool.call" || msg.tool !== "detour_emit_page_event") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const args = msg.arguments ?? {};
|
|
28
|
+
const severity = String(args.severity ?? "info").toLowerCase();
|
|
29
|
+
push(ws, {
|
|
30
|
+
stream: "detour-browser",
|
|
31
|
+
level: /error|fatal|blocked/.test(severity) ? "inject" : "surface",
|
|
32
|
+
event: {
|
|
33
|
+
type: `browser.${args.eventType}`,
|
|
34
|
+
url: args.url ?? null,
|
|
35
|
+
severity,
|
|
36
|
+
message: args.message
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
ws.send(JSON.stringify({ type: "tool.result", callId: msg.callId, result: { ok: true } }));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { connectProvider, push } from "./provider-utils.mjs";
|
|
2
|
+
|
|
3
|
+
const tools = [
|
|
4
|
+
{
|
|
5
|
+
name: "jira_github_emit_issue",
|
|
6
|
+
description: "Emit a normalized Jira issue event for tap goals or orchestration.",
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
issueKey: { type: "string" },
|
|
11
|
+
summary: { type: "string" },
|
|
12
|
+
description: { type: "string" },
|
|
13
|
+
label: { type: "string" },
|
|
14
|
+
prUrl: { type: "string" }
|
|
15
|
+
},
|
|
16
|
+
required: ["issueKey", "summary"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
connectProvider({
|
|
22
|
+
name: "jira-github-template",
|
|
23
|
+
tools,
|
|
24
|
+
onMessage(ws, msg) {
|
|
25
|
+
if (msg.type !== "tool.call" || msg.tool !== "jira_github_emit_issue") {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const args = msg.arguments ?? {};
|
|
29
|
+
push(ws, {
|
|
30
|
+
stream: "jira-github",
|
|
31
|
+
level: "inject",
|
|
32
|
+
event: {
|
|
33
|
+
type: "jira.issue.ready",
|
|
34
|
+
issueKey: args.issueKey,
|
|
35
|
+
summary: args.summary,
|
|
36
|
+
label: args.label,
|
|
37
|
+
prUrl: args.prUrl ?? null
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
ws.send(JSON.stringify({ type: "tool.result", callId: msg.callId, result: { ok: true } }));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import WebSocket from "ws";
|
|
5
|
+
|
|
6
|
+
export function discoverTapToken() {
|
|
7
|
+
if (process.env.TAP_PROVIDER_TOKEN) {
|
|
8
|
+
return process.env.TAP_PROVIDER_TOKEN;
|
|
9
|
+
}
|
|
10
|
+
const copilotHome = process.env.COPILOT_HOME || path.join(os.homedir(), ".copilot");
|
|
11
|
+
return fs.readFileSync(path.join(copilotHome, "extensions", "tap", ".provider-token"), "utf8").trim();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function connectProvider({ name, tools, session = "all", onMessage }) {
|
|
15
|
+
const token = discoverTapToken();
|
|
16
|
+
const ws = new WebSocket(process.env.TAP_PROVIDER_URL || "ws://127.0.0.1:9400");
|
|
17
|
+
ws.on("open", () => {
|
|
18
|
+
ws.send(JSON.stringify({ type: "auth", token }));
|
|
19
|
+
});
|
|
20
|
+
ws.on("message", (raw) => {
|
|
21
|
+
const msg = JSON.parse(String(raw));
|
|
22
|
+
if (msg.type === "sessions") {
|
|
23
|
+
ws.send(JSON.stringify({
|
|
24
|
+
type: "hello",
|
|
25
|
+
name,
|
|
26
|
+
protocolVersion: 2,
|
|
27
|
+
session,
|
|
28
|
+
tools
|
|
29
|
+
}));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
onMessage?.(ws, msg);
|
|
33
|
+
});
|
|
34
|
+
return ws;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function push(ws, { stream, level = "surface", event, metadata = {} }) {
|
|
38
|
+
ws.send(JSON.stringify({
|
|
39
|
+
type: "push",
|
|
40
|
+
level,
|
|
41
|
+
stream,
|
|
42
|
+
event: typeof event === "string" ? event : JSON.stringify(event),
|
|
43
|
+
metadata
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { connectProvider, push } from "./provider-utils.mjs";
|
|
3
|
+
|
|
4
|
+
function fingerprint(finding) {
|
|
5
|
+
return createHash("sha256")
|
|
6
|
+
.update([finding.cwe, finding.sink, finding.file, finding.line].filter(Boolean).join("|"))
|
|
7
|
+
.digest("hex")
|
|
8
|
+
.slice(0, 16);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const tools = [
|
|
12
|
+
{
|
|
13
|
+
name: "sast_emit_findings",
|
|
14
|
+
description: "Normalize SAST findings into stable, fingerprinted tap events.",
|
|
15
|
+
parameters: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
findings: { type: "array" }
|
|
19
|
+
},
|
|
20
|
+
required: ["findings"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
connectProvider({
|
|
26
|
+
name: "sast-triage-template",
|
|
27
|
+
tools,
|
|
28
|
+
onMessage(ws, msg) {
|
|
29
|
+
if (msg.type !== "tool.call" || msg.tool !== "sast_emit_findings") {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const finding of msg.arguments?.findings ?? []) {
|
|
33
|
+
const severity = String(finding.severity ?? "medium").toLowerCase();
|
|
34
|
+
push(ws, {
|
|
35
|
+
stream: "sast-triage",
|
|
36
|
+
level: /critical|high/.test(severity) ? "inject" : "surface",
|
|
37
|
+
event: {
|
|
38
|
+
type: "sast.finding",
|
|
39
|
+
fingerprint: fingerprint(finding),
|
|
40
|
+
severity,
|
|
41
|
+
cwe: finding.cwe,
|
|
42
|
+
file: finding.file,
|
|
43
|
+
line: finding.line,
|
|
44
|
+
sink: finding.sink,
|
|
45
|
+
exploitability: finding.exploitability ?? null
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
ws.send(JSON.stringify({ type: "tool.result", callId: msg.callId, result: { ok: true } }));
|
|
50
|
+
}
|
|
51
|
+
});
|