@ory/github-copilot 0.0.0-stage → 1.5.0
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 +30 -2
- package/dist/cli/assets.d.ts +3 -0
- package/dist/cli/assets.js +120 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +159 -0
- package/dist/handlers.d.ts +8 -0
- package/dist/handlers.js +110 -0
- package/dist/hook.d.ts +8 -0
- package/dist/hook.js +64 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.js +2 -0
- package/package.json +62 -3
package/README.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ory Agent Security for GitHub Copilot CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install the Agent Plugins 1.0 bundle with GitHub Copilot CLI 1.0 or later:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx -y -p @ory/github-copilot ory-copilot install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The plugin contributes the shared Ory skills and MCP server and registers native
|
|
10
|
+
camelCase Copilot hooks. `preToolUse` is the enforcement boundary: enforce-mode
|
|
11
|
+
policy denial returns Copilot's native deny decision, while observe mode and Ory
|
|
12
|
+
infrastructure failures return no decision and exit successfully, preserving
|
|
13
|
+
Copilot's normal permission flow.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx -y -p @ory/github-copilot ory-copilot configure \
|
|
17
|
+
--project-url https://<slug>.projects.oryapis.com \
|
|
18
|
+
--agent-security-url https://agents.console.ory.com
|
|
19
|
+
npx -y -p @ory/github-copilot ory-copilot status
|
|
20
|
+
npx -y -p @ory/github-copilot ory-copilot uninstall
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Copilot command-hook crashes and non-zero exits are fail-closed. The Ory hook
|
|
24
|
+
therefore catches adapter failures and exits 0 with an empty decision. An Ory
|
|
25
|
+
allow result does the same; only an explicit enforce-mode denial overrides
|
|
26
|
+
Copilot's permission handling.
|
|
27
|
+
Copilot hook timeouts are controlled by Copilot itself and are fail-open; Copilot
|
|
28
|
+
surfaces a timeout warning, and the timed-out process may not persist an Ory event.
|
|
29
|
+
|
|
30
|
+
For noninteractive Copilot cloud agent jobs, use the separate repository recipe
|
|
31
|
+
in [`examples/github-copilot-cloud-agent`](../../examples/github-copilot-cloud-agent).
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.wireGitHubCopilotRuntime = wireGitHubCopilotRuntime;
|
|
37
|
+
exports.installPluginAssets = installPluginAssets;
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const argus_1 = require("@ory/argus");
|
|
41
|
+
const PACKAGE_NAME = "@ory/github-copilot";
|
|
42
|
+
const HARNESS = "github-copilot";
|
|
43
|
+
const PACKAGE_ROOT = path.resolve(__dirname, "..", "..");
|
|
44
|
+
const SCHEMA_ROOT = "https://agent-plugins.org/schemas/1.0.0";
|
|
45
|
+
const RENDER_OPTS = {
|
|
46
|
+
binName: "ory-copilot",
|
|
47
|
+
packageName: PACKAGE_NAME,
|
|
48
|
+
};
|
|
49
|
+
const EVENTS = [
|
|
50
|
+
"sessionStart",
|
|
51
|
+
"sessionEnd",
|
|
52
|
+
"userPromptSubmitted",
|
|
53
|
+
"preToolUse",
|
|
54
|
+
"postToolUse",
|
|
55
|
+
"postToolUseFailure",
|
|
56
|
+
"errorOccurred",
|
|
57
|
+
"subagentStart",
|
|
58
|
+
"subagentStop",
|
|
59
|
+
];
|
|
60
|
+
function readPackageVersion() {
|
|
61
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8"));
|
|
62
|
+
return manifest.version;
|
|
63
|
+
}
|
|
64
|
+
function wireGitHubCopilotRuntime(args) {
|
|
65
|
+
return (0, argus_1.wireRuntime)({
|
|
66
|
+
harness: HARNESS,
|
|
67
|
+
packageName: PACKAGE_NAME,
|
|
68
|
+
packageRoot: PACKAGE_ROOT,
|
|
69
|
+
installCommand: "npx -y -p @ory/github-copilot ory-copilot install",
|
|
70
|
+
args,
|
|
71
|
+
fallbackStdout: "{}",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function installPluginAssets(root, runtime) {
|
|
75
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
76
|
+
fs.mkdirSync(root, { recursive: true });
|
|
77
|
+
fs.writeFileSync(path.join(root, "plugin.json"), JSON.stringify({
|
|
78
|
+
$schema: `${SCHEMA_ROOT}/plugin.schema.json`,
|
|
79
|
+
name: "ory-agent-security",
|
|
80
|
+
version: readPackageVersion(),
|
|
81
|
+
description: "Ory authentication, authorization, and activity auditing for GitHub Copilot CLI",
|
|
82
|
+
author: { name: "Ory" },
|
|
83
|
+
homepage: "https://www.ory.com",
|
|
84
|
+
repository: "https://github.com/ory/ory-agent-plugins",
|
|
85
|
+
license: "Apache-2.0",
|
|
86
|
+
keywords: ["ory", "copilot", "agent-security"],
|
|
87
|
+
}, null, 2) + "\n");
|
|
88
|
+
(0, argus_1.writeSkillTree)(path.join(root, "skills"), [
|
|
89
|
+
...(0, argus_1.renderOrySkills)(HARNESS, RENDER_OPTS),
|
|
90
|
+
...(0, argus_1.renderOryCommands)(HARNESS, RENDER_OPTS).map(argus_1.commandToSkill),
|
|
91
|
+
]);
|
|
92
|
+
if (runtime.mcpServer) {
|
|
93
|
+
fs.writeFileSync(path.join(root, "mcp.json"), JSON.stringify({
|
|
94
|
+
$schema: `${SCHEMA_ROOT}/mcp.schema.json`,
|
|
95
|
+
mcpServers: {
|
|
96
|
+
ory: {
|
|
97
|
+
type: "stdio",
|
|
98
|
+
command: runtime.mcpServer.command,
|
|
99
|
+
args: runtime.mcpServer.args,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
}, null, 2) + "\n");
|
|
103
|
+
}
|
|
104
|
+
const command = (0, argus_1.requireHookCommand)(runtime);
|
|
105
|
+
const hooks = {};
|
|
106
|
+
for (const event of EVENTS) {
|
|
107
|
+
hooks[event] = [
|
|
108
|
+
{
|
|
109
|
+
type: "command",
|
|
110
|
+
command: `${command} ${event}`,
|
|
111
|
+
timeoutSec: event === "sessionStart"
|
|
112
|
+
? (0, argus_1.sessionStartHookTimeout)(HARNESS, "seconds")
|
|
113
|
+
: (0, argus_1.toolHookTimeout)(HARNESS, "seconds"),
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
const hooksDir = path.join(root, "com.github.copilot", "hooks");
|
|
118
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
119
|
+
fs.writeFileSync(path.join(hooksDir, "hooks.json"), JSON.stringify({ version: 1, hooks }, null, 2) + "\n");
|
|
120
|
+
}
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const node_child_process_1 = require("node:child_process");
|
|
40
|
+
const argus_1 = require("@ory/argus");
|
|
41
|
+
const assets_js_1 = require("./assets.js");
|
|
42
|
+
const HARNESS = "github-copilot";
|
|
43
|
+
const BIN = "ory-copilot";
|
|
44
|
+
const PACKAGE_ROOT = path.resolve(__dirname, "..", "..");
|
|
45
|
+
const PLUGIN_DIR = path.join((0, argus_1.getHarnessDataDir)(HARNESS), "plugin");
|
|
46
|
+
const SPAWN_VIA_SHELL = process.platform === "win32";
|
|
47
|
+
function runCopilot(args) {
|
|
48
|
+
return (0, node_child_process_1.spawnSync)("copilot", args, {
|
|
49
|
+
encoding: "utf8",
|
|
50
|
+
stdio: "inherit",
|
|
51
|
+
shell: SPAWN_VIA_SHELL,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function install(args) {
|
|
55
|
+
if (args.includes("--print")) {
|
|
56
|
+
console.log(`Would install an Agent Plugins 1.0 bundle from ${PLUGIN_DIR}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const runtime = (0, assets_js_1.wireGitHubCopilotRuntime)(args);
|
|
60
|
+
(0, assets_js_1.installPluginAssets)(PLUGIN_DIR, runtime);
|
|
61
|
+
const result = runCopilot(["plugin", "install", PLUGIN_DIR]);
|
|
62
|
+
if (result.error || result.status !== 0) {
|
|
63
|
+
throw new Error("`copilot plugin install` failed; GitHub Copilot CLI 1.0 or later is required");
|
|
64
|
+
}
|
|
65
|
+
console.log(`Installed the Ory Agent Security plugin from ${PLUGIN_DIR}.`);
|
|
66
|
+
(0, argus_1.printEnvHelp)(BIN);
|
|
67
|
+
}
|
|
68
|
+
function uninstall() {
|
|
69
|
+
const result = runCopilot(["plugin", "uninstall", "ory-agent-security"]);
|
|
70
|
+
if (result.error)
|
|
71
|
+
console.warn("GitHub Copilot CLI was not found; continuing local cleanup.");
|
|
72
|
+
fs.rmSync(PLUGIN_DIR, { recursive: true, force: true });
|
|
73
|
+
(0, argus_1.removeRuntimeWiring)(HARNESS);
|
|
74
|
+
for (const pruned of (0, argus_1.pruneRuntimeStores)())
|
|
75
|
+
console.log(` Removed runtime: ${pruned}`);
|
|
76
|
+
}
|
|
77
|
+
async function status() {
|
|
78
|
+
await (0, argus_1.runStatusCommand)(BIN, HARNESS, {
|
|
79
|
+
title: "GitHub Copilot CLI",
|
|
80
|
+
printPluginSection: () => {
|
|
81
|
+
console.log("Plugin:");
|
|
82
|
+
console.log(` Bundle: ${fs.existsSync(path.join(PLUGIN_DIR, "plugin.json")) ? PLUGIN_DIR : "not installed"}`);
|
|
83
|
+
console.log(` Runtime: ${(0, argus_1.describeRuntimeHealth)((0, argus_1.checkRuntimeHealth)(HARNESS))}`);
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function help() {
|
|
88
|
+
console.log(`
|
|
89
|
+
ory-copilot - Ory plugin for GitHub Copilot CLI
|
|
90
|
+
|
|
91
|
+
Usage:
|
|
92
|
+
npx -y -p @ory/github-copilot ory-copilot <command> [options]
|
|
93
|
+
|
|
94
|
+
Commands:
|
|
95
|
+
install Materialize and install the Agent Plugins 1.0 bundle
|
|
96
|
+
uninstall Remove the Copilot plugin and its Ory runtime wiring
|
|
97
|
+
configure Set or view the Ory Agent Security connection
|
|
98
|
+
agent <cmd> Inspect runtime identity state
|
|
99
|
+
permissions Show live mode and native allowed/blocked state
|
|
100
|
+
status Show plugin and runtime status
|
|
101
|
+
watch Follow the activity/debug log
|
|
102
|
+
version Show package and build versions
|
|
103
|
+
local <cmd> Manage the local Ory dev environment
|
|
104
|
+
`);
|
|
105
|
+
}
|
|
106
|
+
function main() {
|
|
107
|
+
const [command, ...args] = process.argv.slice(2);
|
|
108
|
+
if ((0, argus_1.shouldPrintHelp)(command, args))
|
|
109
|
+
return help();
|
|
110
|
+
switch (command) {
|
|
111
|
+
case "install":
|
|
112
|
+
(0, argus_1.beginDeferNextSteps)();
|
|
113
|
+
install(args);
|
|
114
|
+
void (0, argus_1.runPostInstall)(BIN, HARNESS, args).then(() => process.exit(0), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
115
|
+
break;
|
|
116
|
+
case "uninstall":
|
|
117
|
+
uninstall();
|
|
118
|
+
void (0, argus_1.clearCredentialsForUninstall)({ harness: HARNESS, purge: args.includes("--purge") }).then(() => process.exit(0), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
119
|
+
break;
|
|
120
|
+
case "configure":
|
|
121
|
+
(0, argus_1.runConfigureCommand)(BIN, args);
|
|
122
|
+
break;
|
|
123
|
+
case "agent":
|
|
124
|
+
void (0, argus_1.runAgentCommand)(BIN, HARNESS, args).then((code) => process.exit(code), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
125
|
+
break;
|
|
126
|
+
case "permissions":
|
|
127
|
+
void (0, argus_1.runPermissionsCommand)(BIN, HARNESS, args).then((code) => process.exit(code), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
128
|
+
break;
|
|
129
|
+
case "status":
|
|
130
|
+
void status().then(() => process.exit(0), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
131
|
+
break;
|
|
132
|
+
case "watch":
|
|
133
|
+
void (0, argus_1.runWatchCommand)(BIN, HARNESS, args).then((code) => process.exit(code), (err) => { console.error(err.message ?? err); process.exit(1); });
|
|
134
|
+
break;
|
|
135
|
+
case "local":
|
|
136
|
+
void (0, argus_1.runLocalCommand)(BIN, args).catch((err) => { console.error(err.message ?? err); process.exit(1); });
|
|
137
|
+
break;
|
|
138
|
+
case "version":
|
|
139
|
+
case "--version":
|
|
140
|
+
case "-v": process.exit((0, argus_1.runVersionCommand)(BIN, args, { packageRoot: PACKAGE_ROOT }));
|
|
141
|
+
case "help":
|
|
142
|
+
case "--help":
|
|
143
|
+
case "-h":
|
|
144
|
+
case undefined:
|
|
145
|
+
help();
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
console.error(`Unknown command: ${command}`);
|
|
149
|
+
help();
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
main();
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.error(err instanceof Error ? err.message : err);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { OryAgentClient, ensureAgentIdentity, ensureSubAgentIdentity, ensureUserAuthenticated } from "@ory/argus";
|
|
2
|
+
import type { GitHubCopilotHookEvent, GitHubCopilotHookInput, GitHubCopilotHookOutput } from "./types.js";
|
|
3
|
+
export interface HandleHookEventDeps {
|
|
4
|
+
userLogin?: typeof ensureUserAuthenticated;
|
|
5
|
+
agentGate?: typeof ensureAgentIdentity;
|
|
6
|
+
subAgentGate?: typeof ensureSubAgentIdentity;
|
|
7
|
+
}
|
|
8
|
+
export declare function handleHookEvent(event: GitHubCopilotHookEvent, input: GitHubCopilotHookInput, client: OryAgentClient, deps?: HandleHookEventDeps): Promise<GitHubCopilotHookOutput>;
|
package/dist/handlers.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleHookEvent = handleHookEvent;
|
|
4
|
+
const argus_1 = require("@ory/argus");
|
|
5
|
+
const HARNESS = "github-copilot";
|
|
6
|
+
function toolArgs(input) {
|
|
7
|
+
if (typeof input.toolArgs !== "string")
|
|
8
|
+
return input.toolArgs;
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(input.toolArgs);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return input.toolArgs;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function handleHookEvent(event, input, client, deps = {}) {
|
|
17
|
+
client.logger.debug("hook.received", {
|
|
18
|
+
event,
|
|
19
|
+
sessionId: input.sessionId,
|
|
20
|
+
toolName: input.toolName,
|
|
21
|
+
});
|
|
22
|
+
return (0, argus_1.withHookContext)(client, { sessionId: input.sessionId }, async () => {
|
|
23
|
+
switch (event) {
|
|
24
|
+
case "sessionStart":
|
|
25
|
+
await (0, argus_1.sessionStart)(client, {
|
|
26
|
+
binName: "ory-copilot",
|
|
27
|
+
harness: HARNESS,
|
|
28
|
+
userLogin: deps.userLogin,
|
|
29
|
+
agentGate: deps.agentGate,
|
|
30
|
+
activityAttributes: { source: input.source },
|
|
31
|
+
});
|
|
32
|
+
return {};
|
|
33
|
+
case "preToolUse": {
|
|
34
|
+
const result = await (0, argus_1.gate)(client, {
|
|
35
|
+
harness: HARNESS,
|
|
36
|
+
toolName: input.toolName ?? "unknown",
|
|
37
|
+
toolArgs: toolArgs(input),
|
|
38
|
+
subjectFallback: input.sessionId ? `session:${input.sessionId}` : undefined,
|
|
39
|
+
});
|
|
40
|
+
return result.blocked
|
|
41
|
+
? {
|
|
42
|
+
permissionDecision: "deny",
|
|
43
|
+
permissionDecisionReason: result.denialMessage,
|
|
44
|
+
}
|
|
45
|
+
: {};
|
|
46
|
+
}
|
|
47
|
+
case "postToolUse":
|
|
48
|
+
(0, argus_1.complete)(client, {
|
|
49
|
+
toolName: input.toolName ?? "unknown",
|
|
50
|
+
input: toolArgs(input),
|
|
51
|
+
output: input.toolResult?.textResultForLlm,
|
|
52
|
+
});
|
|
53
|
+
return {};
|
|
54
|
+
case "postToolUseFailure":
|
|
55
|
+
(0, argus_1.fail)(client, {
|
|
56
|
+
toolName: input.toolName ?? "unknown",
|
|
57
|
+
input: toolArgs(input),
|
|
58
|
+
error: input.error,
|
|
59
|
+
});
|
|
60
|
+
return {};
|
|
61
|
+
case "userPromptSubmitted":
|
|
62
|
+
client.logger.activity("user.prompt", "ok", {
|
|
63
|
+
attributes: { promptLen: input.prompt?.length },
|
|
64
|
+
});
|
|
65
|
+
return {};
|
|
66
|
+
case "subagentStart": {
|
|
67
|
+
const subAgentType = input.agentName ?? input.agentType;
|
|
68
|
+
client.logger.activity("subagent.start", "ok", {
|
|
69
|
+
attributes: { subAgentType, subAgentId: input.agentId },
|
|
70
|
+
});
|
|
71
|
+
if (subAgentType && (0, argus_1.isSecurityConnected)()) {
|
|
72
|
+
await (0, argus_1.registerSubagent)(client, {
|
|
73
|
+
harness: HARNESS,
|
|
74
|
+
subAgentType,
|
|
75
|
+
perSpawnId: input.agentId,
|
|
76
|
+
subAgentGate: deps.subAgentGate,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
case "subagentStop":
|
|
82
|
+
client.logger.activity("subagent.stop", "ok", {
|
|
83
|
+
attributes: {
|
|
84
|
+
subAgentType: input.agentName ?? input.agentType,
|
|
85
|
+
subAgentId: input.agentId,
|
|
86
|
+
stopReason: input.stopReason,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
return {};
|
|
90
|
+
case "errorOccurred":
|
|
91
|
+
client.logger.activity("session.error", "error", {
|
|
92
|
+
attributes: {
|
|
93
|
+
errorContext: input.errorContext,
|
|
94
|
+
recoverable: input.recoverable,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
return {};
|
|
98
|
+
case "sessionEnd":
|
|
99
|
+
client.logger.activity("session.end", "ok", {
|
|
100
|
+
attributes: { reason: input.reason },
|
|
101
|
+
});
|
|
102
|
+
return {};
|
|
103
|
+
default:
|
|
104
|
+
client.logger.activity("hook.passthrough", "skipped", {
|
|
105
|
+
attributes: { event },
|
|
106
|
+
});
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
package/dist/hook.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { OryAgentClient } from "@ory/argus";
|
|
3
|
+
import { handleHookEvent } from "./handlers.js";
|
|
4
|
+
import type { GitHubCopilotHookEvent } from "./types.js";
|
|
5
|
+
type HookHandler = typeof handleHookEvent;
|
|
6
|
+
export declare function processHookInput(event: GitHubCopilotHookEvent, rawInput: string, hookClient: OryAgentClient, handler?: HookHandler): Promise<string>;
|
|
7
|
+
export declare function main(): Promise<void>;
|
|
8
|
+
export {};
|
package/dist/hook.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.processHookInput = processHookInput;
|
|
5
|
+
exports.main = main;
|
|
6
|
+
const argus_1 = require("@ory/argus");
|
|
7
|
+
const handlers_js_1 = require("./handlers.js");
|
|
8
|
+
const FAIL_OPEN = {};
|
|
9
|
+
const EVENT_FLUSH_TIMEOUT_MS = 750;
|
|
10
|
+
let client;
|
|
11
|
+
async function readStdin() {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
15
|
+
process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
16
|
+
process.stdin.on("error", reject);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async function flushEvents() {
|
|
20
|
+
try {
|
|
21
|
+
await client?.flushEvents(EVENT_FLUSH_TIMEOUT_MS);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Activity delivery never changes the hook decision.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function processHookInput(event, rawInput, hookClient, handler = handlers_js_1.handleHookEvent) {
|
|
28
|
+
let input;
|
|
29
|
+
try {
|
|
30
|
+
input = JSON.parse(rawInput);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
hookClient.logger.error("hook.stdin.parse_failed", {
|
|
34
|
+
message: err instanceof Error ? err.message : String(err),
|
|
35
|
+
});
|
|
36
|
+
return JSON.stringify(FAIL_OPEN);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return JSON.stringify(await handler(event, input, hookClient));
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
hookClient.logger.error("hook.handler.error", {
|
|
43
|
+
event,
|
|
44
|
+
message: err instanceof Error ? err.message : String(err),
|
|
45
|
+
});
|
|
46
|
+
return JSON.stringify(FAIL_OPEN);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function main() {
|
|
50
|
+
client = argus_1.OryAgentClient.fromEnv("github-copilot");
|
|
51
|
+
const event = process.argv[2];
|
|
52
|
+
if (!event)
|
|
53
|
+
throw new Error("Missing GitHub Copilot hook event argument");
|
|
54
|
+
process.stdout.write(await processHookInput(event, await readStdin(), client));
|
|
55
|
+
await flushEvents();
|
|
56
|
+
}
|
|
57
|
+
if (require.main === module) {
|
|
58
|
+
main().then(() => process.exit(0), async (err) => {
|
|
59
|
+
process.stderr.write(`[ory-agent] fatal: ${err}\n`);
|
|
60
|
+
process.stdout.write(JSON.stringify(FAIL_OPEN));
|
|
61
|
+
await flushEvents();
|
|
62
|
+
process.exit(0);
|
|
63
|
+
});
|
|
64
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { handleHookEvent } from "./handlers.js";
|
|
2
|
+
export type { HandleHookEventDeps } from "./handlers.js";
|
|
3
|
+
export type { GitHubCopilotHookEvent, GitHubCopilotHookInput, GitHubCopilotHookOutput, } from "./types.js";
|
|
4
|
+
export { installPluginAssets } from "./cli/assets.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installPluginAssets = exports.handleHookEvent = void 0;
|
|
4
|
+
var handlers_js_1 = require("./handlers.js");
|
|
5
|
+
Object.defineProperty(exports, "handleHookEvent", { enumerable: true, get: function () { return handlers_js_1.handleHookEvent; } });
|
|
6
|
+
var assets_js_1 = require("./cli/assets.js");
|
|
7
|
+
Object.defineProperty(exports, "installPluginAssets", { enumerable: true, get: function () { return assets_js_1.installPluginAssets; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** GitHub Copilot CLI's native camelCase command-hook contract. */
|
|
2
|
+
export interface GitHubCopilotHookInput {
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
timestamp?: number;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
source?: "startup" | "resume" | "new" | string;
|
|
7
|
+
initialPrompt?: string;
|
|
8
|
+
prompt?: string;
|
|
9
|
+
toolName?: string;
|
|
10
|
+
/** Copilot may deliver this as an object or as a JSON string. */
|
|
11
|
+
toolArgs?: unknown;
|
|
12
|
+
toolResult?: {
|
|
13
|
+
resultType?: string;
|
|
14
|
+
textResultForLlm?: string;
|
|
15
|
+
};
|
|
16
|
+
error?: string | {
|
|
17
|
+
message?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
stack?: string;
|
|
20
|
+
};
|
|
21
|
+
errorContext?: string;
|
|
22
|
+
recoverable?: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
transcriptPath?: string;
|
|
25
|
+
agentId?: string;
|
|
26
|
+
agentType?: string;
|
|
27
|
+
agentName?: string;
|
|
28
|
+
agentDisplayName?: string;
|
|
29
|
+
agentDescription?: string;
|
|
30
|
+
response?: string;
|
|
31
|
+
stopReason?: string;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
export type GitHubCopilotHookEvent = "sessionStart" | "sessionEnd" | "userPromptSubmitted" | "preToolUse" | "postToolUse" | "postToolUseFailure" | "errorOccurred" | "subagentStart" | "subagentStop" | string;
|
|
35
|
+
export interface GitHubCopilotHookOutput {
|
|
36
|
+
permissionDecision?: "allow" | "deny" | "ask";
|
|
37
|
+
permissionDecisionReason?: string;
|
|
38
|
+
additionalContext?: string;
|
|
39
|
+
}
|
package/dist/types.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/github-copilot",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Ory plugin for GitHub Copilot CLI: skills, local Ory tooling, and authentication, authorization, and audit for every tool call",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://github.com/ory/ory-agent-plugins/tree/main/packages/github-copilot",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/ory/ory-agent-plugins/issues"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"ory",
|
|
12
|
+
"github-copilot",
|
|
13
|
+
"copilot-cli",
|
|
14
|
+
"hooks",
|
|
15
|
+
"plugin",
|
|
16
|
+
"authentication",
|
|
17
|
+
"authorization",
|
|
18
|
+
"permissions",
|
|
19
|
+
"audit",
|
|
20
|
+
"agent-security",
|
|
21
|
+
"mcp"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org/",
|
|
26
|
+
"provenance": true
|
|
27
|
+
},
|
|
28
|
+
"reova": {
|
|
29
|
+
"enabled": true,
|
|
30
|
+
"endpoint": "https://telemetry.reo.dev/data"
|
|
31
|
+
},
|
|
32
|
+
"main": "dist/index.js",
|
|
33
|
+
"types": "dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./dist/index.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"bin": {
|
|
41
|
+
"ory-copilot": "dist/cli/main.js",
|
|
42
|
+
"ory-copilot-hook": "dist/hook.js"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist",
|
|
46
|
+
"!dist/**/*.tsbuildinfo"
|
|
47
|
+
],
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"reova": "^0.7.0",
|
|
50
|
+
"@ory/argus": "1.5.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"typescript": "^6.0.2"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=22"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"test:watch": "vitest",
|
|
63
|
+
"typecheck": "tsc --noEmit"
|
|
64
|
+
}
|
|
6
65
|
}
|