@ory/amp 0.10.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.
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Amp (Sourcegraph's coding agent) plugin types.
3
+ *
4
+ * Verified against the installed `amp` binary (Bun-compiled, embedded JS
5
+ * bundle exposing the `@ampcode/plugin` API). Amp's integration is a HYBRID
6
+ * of two mechanisms:
7
+ *
8
+ * 1. Permission delegate helper (PRIMARY, blocking) — a standalone
9
+ * program named in `amp.permissions` as `{ tool, action: "delegate",
10
+ * to: "<program>" }`. Amp invokes it as a subprocess, passing the tool
11
+ * parameters as JSON on stdin. The program decides by exit code:
12
+ * 0 = allow, 1 = ask the user, ≥2 = reject (stderr → model reason).
13
+ * A 10-second delegate timeout applies (a timed-out delegate is
14
+ * treated as a reject). See `AmpDelegateInput` below.
15
+ *
16
+ * 2. In-process plugin (SECONDARY, tracing/auth) — a default-exported
17
+ * factory placed under `.amp/plugins/*.ts` that receives a `PluginAPI`
18
+ * (the `@ampcode/plugin` contract). Runs under Bun's TypeScript
19
+ * runtime. Used here ONLY for advisory session-start auth and
20
+ * post-tool tracing; the blocking decision lives in the delegate
21
+ * helper for cleaner subprocess parity.
22
+ *
23
+ * We model the `@ampcode/plugin` API surface locally (the plugin package
24
+ * takes no harness SDK dependency — see AGENTS.md). The shapes mirror the
25
+ * binary's `PluginEventMap` / `PluginEventContext` exactly.
26
+ */
27
+ /**
28
+ * JSON payload Amp writes to the delegate program's stdin.
29
+ *
30
+ * The delegate receives the tool name and its arguments. We read several
31
+ * plausible spellings for the tool name (`tool` / `toolName` / `name`) and
32
+ * arguments (`input` / `params` / `arguments` / `args`) so the helper
33
+ * degrades gracefully across Amp revisions; anything we cannot find falls
34
+ * back to "unknown", which fails open (allow) per the design rules.
35
+ */
36
+ export interface AmpDelegateInput {
37
+ /** Tool being invoked (canonical: `tool`). */
38
+ tool?: string;
39
+ /** Alternate spellings tolerated for forward/backward compatibility. */
40
+ toolName?: string;
41
+ name?: string;
42
+ /** Tool parameters (canonical: `input`). */
43
+ input?: Record<string, unknown>;
44
+ params?: Record<string, unknown>;
45
+ arguments?: Record<string, unknown>;
46
+ args?: Record<string, unknown>;
47
+ /** Optional session/thread correlation id, if Amp supplies one. */
48
+ threadID?: string;
49
+ sessionID?: string;
50
+ session_id?: string;
51
+ [key: string]: unknown;
52
+ }
53
+ /**
54
+ * Exit codes the delegate program returns to Amp.
55
+ * NOTE the inversion vs. other harnesses: deny is exit ≥2, not exit 0/1.
56
+ */
57
+ export declare const AMP_DELEGATE_EXIT: {
58
+ /** Allow the tool call. */
59
+ readonly ALLOW: 0;
60
+ /**
61
+ * Ask the user. Reserved — not produced by this version. Ory observe
62
+ * mode passes through (exit 0) and enforce mode rejects (exit 2); there
63
+ * is no "ask Ory then ask the user" middle state yet.
64
+ */
65
+ readonly ASK: 1;
66
+ /** Reject the tool call; stderr is forwarded to the model as the reason. */
67
+ readonly REJECT: 2;
68
+ };
69
+ /** Thread reference carried on every plugin event. */
70
+ export interface AmpThreadRef {
71
+ id: string;
72
+ [key: string]: unknown;
73
+ }
74
+ /**
75
+ * The result an in-process `tool.call` handler can return to influence a
76
+ * tool invocation. We never return a blocking action from the in-process
77
+ * plugin — the delegate helper owns blocking — but the type is modeled in
78
+ * full to match `@ampcode/plugin`.
79
+ */
80
+ export type AmpToolCallResult = {
81
+ action: "allow";
82
+ } | {
83
+ action: "reject-and-continue";
84
+ message: string;
85
+ } | {
86
+ action: "modify";
87
+ input: Record<string, unknown>;
88
+ } | {
89
+ action: "synthesize";
90
+ result: {
91
+ output: string;
92
+ exitCode?: number;
93
+ };
94
+ } | {
95
+ action: "error";
96
+ message: string;
97
+ };
98
+ /** `session.start` — a new thread/session begins. */
99
+ export interface AmpSessionStartEvent {
100
+ thread: AmpThreadRef;
101
+ [key: string]: unknown;
102
+ }
103
+ /** `agent.start` — the user submitted a prompt; a turn begins. */
104
+ export interface AmpAgentStartEvent {
105
+ thread: AmpThreadRef;
106
+ [key: string]: unknown;
107
+ }
108
+ /** `tool.call` — a tool is about to execute (pre-execution). */
109
+ export interface AmpToolCallEvent {
110
+ toolUseID: string;
111
+ tool: string;
112
+ input: Record<string, unknown>;
113
+ thread: AmpThreadRef;
114
+ [key: string]: unknown;
115
+ }
116
+ /** `tool.result` — a tool finished executing (post-execution). */
117
+ export interface AmpToolResultEvent {
118
+ toolUseID: string;
119
+ tool: string;
120
+ input: Record<string, unknown>;
121
+ status: "done" | "error" | "cancelled";
122
+ error?: string;
123
+ output?: unknown;
124
+ thread: AmpThreadRef;
125
+ [key: string]: unknown;
126
+ }
127
+ /** `agent.end` — a turn ended, carrying the produced messages. */
128
+ export interface AmpAgentEndEvent {
129
+ thread: AmpThreadRef;
130
+ messages?: unknown[];
131
+ [key: string]: unknown;
132
+ }
133
+ /**
134
+ * Context (`PluginEventContext`) passed as the SECOND argument to every
135
+ * handler. Carries Amp's UI helpers, a shell runner (`$`), etc. Modeled as
136
+ * an open object — this plugin only authenticates and traces, so it does
137
+ * not depend on any specific context member.
138
+ */
139
+ export interface AmpPluginEventContext {
140
+ [key: string]: unknown;
141
+ }
142
+ /**
143
+ * Map of Amp plugin event name → payload type. Handlers receive the payload
144
+ * as the first arg and a `PluginEventContext` as the second.
145
+ */
146
+ export interface AmpEventMap {
147
+ "session.start": AmpSessionStartEvent;
148
+ "agent.start": AmpAgentStartEvent;
149
+ "tool.call": AmpToolCallEvent;
150
+ "tool.result": AmpToolResultEvent;
151
+ "agent.end": AmpAgentEndEvent;
152
+ }
153
+ export type AmpEvent = keyof AmpEventMap;
154
+ /** Return type for each event handler. */
155
+ export interface AmpEventReturn {
156
+ "session.start": void;
157
+ "agent.start": void;
158
+ "tool.call": void | AmpToolCallResult;
159
+ "tool.result": void;
160
+ "agent.end": void;
161
+ }
162
+ /** Handler signature for a given event: `(event, ctx) => result`. */
163
+ export type AmpEventHandler<E extends AmpEvent> = (event: AmpEventMap[E], ctx: AmpPluginEventContext) => AmpEventReturn[E] | Promise<AmpEventReturn[E]>;
164
+ /**
165
+ * The PluginAPI object Amp passes to the default-exported plugin factory
166
+ * (`@ampcode/plugin`'s `PluginAPI`).
167
+ */
168
+ export interface AmpPluginApi {
169
+ /** Subscribe to a lifecycle event. */
170
+ on<E extends AmpEvent>(event: E, handler: AmpEventHandler<E>): void;
171
+ /** Register a custom tool. Unused by this plugin; modeled for completeness. */
172
+ registerTool?: (name: string, def: unknown) => void;
173
+ [key: string]: unknown;
174
+ }
175
+ /** The default-exported plugin factory Amp invokes at load time. */
176
+ export type AmpPlugin = (api: AmpPluginApi) => void | Promise<void>;
package/dist/types.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * Amp (Sourcegraph's coding agent) plugin types.
4
+ *
5
+ * Verified against the installed `amp` binary (Bun-compiled, embedded JS
6
+ * bundle exposing the `@ampcode/plugin` API). Amp's integration is a HYBRID
7
+ * of two mechanisms:
8
+ *
9
+ * 1. Permission delegate helper (PRIMARY, blocking) — a standalone
10
+ * program named in `amp.permissions` as `{ tool, action: "delegate",
11
+ * to: "<program>" }`. Amp invokes it as a subprocess, passing the tool
12
+ * parameters as JSON on stdin. The program decides by exit code:
13
+ * 0 = allow, 1 = ask the user, ≥2 = reject (stderr → model reason).
14
+ * A 10-second delegate timeout applies (a timed-out delegate is
15
+ * treated as a reject). See `AmpDelegateInput` below.
16
+ *
17
+ * 2. In-process plugin (SECONDARY, tracing/auth) — a default-exported
18
+ * factory placed under `.amp/plugins/*.ts` that receives a `PluginAPI`
19
+ * (the `@ampcode/plugin` contract). Runs under Bun's TypeScript
20
+ * runtime. Used here ONLY for advisory session-start auth and
21
+ * post-tool tracing; the blocking decision lives in the delegate
22
+ * helper for cleaner subprocess parity.
23
+ *
24
+ * We model the `@ampcode/plugin` API surface locally (the plugin package
25
+ * takes no harness SDK dependency — see AGENTS.md). The shapes mirror the
26
+ * binary's `PluginEventMap` / `PluginEventContext` exactly.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.AMP_DELEGATE_EXIT = void 0;
30
+ /**
31
+ * Exit codes the delegate program returns to Amp.
32
+ * NOTE the inversion vs. other harnesses: deny is exit ≥2, not exit 0/1.
33
+ */
34
+ exports.AMP_DELEGATE_EXIT = {
35
+ /** Allow the tool call. */
36
+ ALLOW: 0,
37
+ /**
38
+ * Ask the user. Reserved — not produced by this version. Ory observe
39
+ * mode passes through (exit 0) and enforce mode rejects (exit 2); there
40
+ * is no "ask Ory then ask the user" middle state yet.
41
+ */
42
+ ASK: 1,
43
+ /** Reject the tool call; stderr is forwarded to the model as the reason. */
44
+ REJECT: 2,
45
+ };
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@ory/amp",
3
+ "version": "0.10.0",
4
+ "description": "Ory plugin for Amp (Sourcegraph's coding agent): a permission delegate that authorizes every tool call plus an in-process plugin for session auth and audit tracing",
5
+ "license": "Apache-2.0",
6
+ "homepage": "https://ory.com",
7
+ "keywords": [
8
+ "ory",
9
+ "amp",
10
+ "ampcode",
11
+ "sourcegraph",
12
+ "coding-agent",
13
+ "permissions",
14
+ "plugin",
15
+ "delegate",
16
+ "identity",
17
+ "identity-management",
18
+ "iam",
19
+ "authentication",
20
+ "authorization",
21
+ "access-control",
22
+ "rbac",
23
+ "zanzibar",
24
+ "oauth",
25
+ "oauth2",
26
+ "openid-connect",
27
+ "oidc",
28
+ "session",
29
+ "mfa",
30
+ "sso",
31
+ "audit",
32
+ "audit-log",
33
+ "compliance",
34
+ "agent",
35
+ "ai-agent",
36
+ "agent-security",
37
+ "guardrails",
38
+ "llm",
39
+ "tracing",
40
+ "distributed-tracing",
41
+ "observability",
42
+ "kratos",
43
+ "keto",
44
+ "hydra"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "registry": "https://registry.npmjs.org/",
49
+ "provenance": true
50
+ },
51
+ "main": "dist/index.js",
52
+ "types": "dist/index.d.ts",
53
+ "exports": {
54
+ ".": {
55
+ "types": "./dist/index.d.ts",
56
+ "default": "./dist/index.js"
57
+ }
58
+ },
59
+ "bin": {
60
+ "ory-amp": "dist/cli/main.js",
61
+ "ory-amp-permission": "dist/permission.js",
62
+ "ory-amp-setup": "dist/cli/setup.js"
63
+ },
64
+ "files": [
65
+ "dist",
66
+ "!dist/dev",
67
+ "!dist/**/*.tsbuildinfo"
68
+ ],
69
+ "dependencies": {
70
+ "@ory/argus": "0.10.0"
71
+ },
72
+ "devDependencies": {
73
+ "typescript": "^6.0.2",
74
+ "vitest": "4.1.4"
75
+ },
76
+ "engines": {
77
+ "node": ">=22"
78
+ },
79
+ "scripts": {
80
+ "build": "tsc",
81
+ "clean": "rm -rf dist *.tsbuildinfo",
82
+ "test": "vitest run",
83
+ "test:watch": "vitest",
84
+ "typecheck": "tsc --noEmit",
85
+ "dev": "node dist/dev/launcher.js"
86
+ }
87
+ }