@github/copilot-sdk 0.2.2 → 0.3.0-preview.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/README.md +2 -2
- package/dist/cjs/client.js +60 -16
- package/dist/cjs/extension.js +2 -4
- package/dist/cjs/generated/rpc.js +40 -10
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/session.js +5 -4
- package/dist/cjs/sessionFsProvider.js +121 -0
- package/dist/cjs/types.js +52 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.js +60 -16
- package/dist/extension.d.ts +1 -1
- package/dist/extension.js +3 -3
- package/dist/generated/rpc.d.ts +1366 -1022
- package/dist/generated/rpc.js +40 -10
- package/dist/generated/session-events.d.ts +3863 -2894
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -1
- package/dist/session.js +5 -4
- package/dist/sessionFsProvider.d.ts +44 -0
- package/dist/sessionFsProvider.js +97 -0
- package/dist/types.d.ts +119 -16
- package/dist/types.js +49 -1
- package/docs/agent-author.md +22 -14
- package/docs/examples.md +35 -31
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { CopilotClient } from "./client.js";
|
|
7
7
|
export { CopilotSession, type AssistantMessageEvent } from "./session.js";
|
|
8
|
-
export { defineTool, approveAll, SYSTEM_PROMPT_SECTIONS } from "./types.js";
|
|
9
|
-
export type { CommandContext, CommandDefinition, CommandHandler, ConnectionState, CopilotClientOptions, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, InputOptions,
|
|
8
|
+
export { defineTool, approveAll, convertMcpCallToolResult, createSessionFsAdapter, SYSTEM_PROMPT_SECTIONS, } from "./types.js";
|
|
9
|
+
export type { CommandContext, CommandDefinition, CommandHandler, ConnectionState, CopilotClientOptions, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, InputOptions, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ProviderConfig, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType, SessionLifecycleHandler, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemPromptSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { CopilotClient } from "./client.js";
|
|
2
2
|
import { CopilotSession } from "./session.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
defineTool,
|
|
5
|
+
approveAll,
|
|
6
|
+
convertMcpCallToolResult,
|
|
7
|
+
createSessionFsAdapter,
|
|
8
|
+
SYSTEM_PROMPT_SECTIONS
|
|
9
|
+
} from "./types.js";
|
|
4
10
|
export {
|
|
5
11
|
CopilotClient,
|
|
6
12
|
CopilotSession,
|
|
7
13
|
SYSTEM_PROMPT_SECTIONS,
|
|
8
14
|
approveAll,
|
|
15
|
+
convertMcpCallToolResult,
|
|
16
|
+
createSessionFsAdapter,
|
|
9
17
|
defineTool
|
|
10
18
|
};
|
package/dist/session.js
CHANGED
|
@@ -100,7 +100,8 @@ class CopilotSession {
|
|
|
100
100
|
sessionId: this.sessionId,
|
|
101
101
|
prompt: options.prompt,
|
|
102
102
|
attachments: options.attachments,
|
|
103
|
-
mode: options.mode
|
|
103
|
+
mode: options.mode,
|
|
104
|
+
requestHeaders: options.requestHeaders
|
|
104
105
|
});
|
|
105
106
|
return response.messageId;
|
|
106
107
|
}
|
|
@@ -324,7 +325,7 @@ class CopilotSession {
|
|
|
324
325
|
await this.rpc.permissions.handlePendingPermissionRequest({
|
|
325
326
|
requestId,
|
|
326
327
|
result: {
|
|
327
|
-
kind: "
|
|
328
|
+
kind: "user-not-available"
|
|
328
329
|
}
|
|
329
330
|
});
|
|
330
331
|
} catch (rpcError) {
|
|
@@ -602,7 +603,7 @@ class CopilotSession {
|
|
|
602
603
|
*/
|
|
603
604
|
async _handlePermissionRequestV2(request) {
|
|
604
605
|
if (!this.permissionHandler) {
|
|
605
|
-
return { kind: "
|
|
606
|
+
return { kind: "user-not-available" };
|
|
606
607
|
}
|
|
607
608
|
try {
|
|
608
609
|
const result = await this.permissionHandler(request, {
|
|
@@ -616,7 +617,7 @@ class CopilotSession {
|
|
|
616
617
|
if (error instanceof Error && error.message === NO_RESULT_PERMISSION_V2_ERROR) {
|
|
617
618
|
throw error;
|
|
618
619
|
}
|
|
619
|
-
return { kind: "
|
|
620
|
+
return { kind: "user-not-available" };
|
|
620
621
|
}
|
|
621
622
|
}
|
|
622
623
|
/**
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SessionFsHandler, SessionFsStatResult, SessionFsReaddirWithTypesEntry } from "./generated/rpc.js";
|
|
2
|
+
/**
|
|
3
|
+
* File metadata returned by {@link SessionFsProvider.stat}.
|
|
4
|
+
* Same shape as the generated {@link SessionFsStatResult} but without the
|
|
5
|
+
* `error` field, since providers signal errors by throwing.
|
|
6
|
+
*/
|
|
7
|
+
export type SessionFsFileInfo = Omit<SessionFsStatResult, "error">;
|
|
8
|
+
/**
|
|
9
|
+
* Interface for session filesystem providers. Implementors use idiomatic
|
|
10
|
+
* TypeScript patterns: throw on error, return values directly. Use
|
|
11
|
+
* {@link createSessionFsAdapter} to convert a provider into the
|
|
12
|
+
* {@link SessionFsHandler} expected by the SDK.
|
|
13
|
+
*
|
|
14
|
+
* Errors with a `code` property of `"ENOENT"` are mapped to the ENOENT
|
|
15
|
+
* error code; all others map to UNKNOWN.
|
|
16
|
+
*/
|
|
17
|
+
export interface SessionFsProvider {
|
|
18
|
+
/** Reads the full content of a file. Throw if the file does not exist. */
|
|
19
|
+
readFile(path: string): Promise<string>;
|
|
20
|
+
/** Writes content to a file, creating parent directories if needed. */
|
|
21
|
+
writeFile(path: string, content: string, mode?: number): Promise<void>;
|
|
22
|
+
/** Appends content to a file, creating parent directories if needed. */
|
|
23
|
+
appendFile(path: string, content: string, mode?: number): Promise<void>;
|
|
24
|
+
/** Checks whether a path exists. */
|
|
25
|
+
exists(path: string): Promise<boolean>;
|
|
26
|
+
/** Gets metadata about a file or directory. Throw if it does not exist. */
|
|
27
|
+
stat(path: string): Promise<SessionFsFileInfo>;
|
|
28
|
+
/** Creates a directory. If recursive is true, creates parents as needed. */
|
|
29
|
+
mkdir(path: string, recursive: boolean, mode?: number): Promise<void>;
|
|
30
|
+
/** Lists entry names in a directory. Throw if it does not exist. */
|
|
31
|
+
readdir(path: string): Promise<string[]>;
|
|
32
|
+
/** Lists entries with type info. Throw if the directory does not exist. */
|
|
33
|
+
readdirWithTypes(path: string): Promise<SessionFsReaddirWithTypesEntry[]>;
|
|
34
|
+
/** Removes a file or directory. If force is true, do not throw on ENOENT. */
|
|
35
|
+
rm(path: string, recursive: boolean, force: boolean): Promise<void>;
|
|
36
|
+
/** Renames/moves a file or directory. */
|
|
37
|
+
rename(src: string, dest: string): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wraps a {@link SessionFsProvider} into the {@link SessionFsHandler}
|
|
41
|
+
* interface expected by the SDK, converting thrown errors into
|
|
42
|
+
* {@link SessionFsError} results.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createSessionFsAdapter(provider: SessionFsProvider): SessionFsHandler;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
function createSessionFsAdapter(provider) {
|
|
2
|
+
return {
|
|
3
|
+
readFile: async ({ path }) => {
|
|
4
|
+
try {
|
|
5
|
+
const content = await provider.readFile(path);
|
|
6
|
+
return { content };
|
|
7
|
+
} catch (err) {
|
|
8
|
+
return { content: "", error: toSessionFsError(err) };
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
writeFile: async ({ path, content, mode }) => {
|
|
12
|
+
try {
|
|
13
|
+
await provider.writeFile(path, content, mode);
|
|
14
|
+
return void 0;
|
|
15
|
+
} catch (err) {
|
|
16
|
+
return toSessionFsError(err);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
appendFile: async ({ path, content, mode }) => {
|
|
20
|
+
try {
|
|
21
|
+
await provider.appendFile(path, content, mode);
|
|
22
|
+
return void 0;
|
|
23
|
+
} catch (err) {
|
|
24
|
+
return toSessionFsError(err);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
exists: async ({ path }) => {
|
|
28
|
+
try {
|
|
29
|
+
return { exists: await provider.exists(path) };
|
|
30
|
+
} catch {
|
|
31
|
+
return { exists: false };
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
stat: async ({ path }) => {
|
|
35
|
+
try {
|
|
36
|
+
return await provider.stat(path);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
return {
|
|
39
|
+
isFile: false,
|
|
40
|
+
isDirectory: false,
|
|
41
|
+
size: 0,
|
|
42
|
+
mtime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43
|
+
birthtime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44
|
+
error: toSessionFsError(err)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
mkdir: async ({ path, recursive, mode }) => {
|
|
49
|
+
try {
|
|
50
|
+
await provider.mkdir(path, recursive ?? false, mode);
|
|
51
|
+
return void 0;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return toSessionFsError(err);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
readdir: async ({ path }) => {
|
|
57
|
+
try {
|
|
58
|
+
const entries = await provider.readdir(path);
|
|
59
|
+
return { entries };
|
|
60
|
+
} catch (err) {
|
|
61
|
+
return { entries: [], error: toSessionFsError(err) };
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
readdirWithTypes: async ({ path }) => {
|
|
65
|
+
try {
|
|
66
|
+
const entries = await provider.readdirWithTypes(path);
|
|
67
|
+
return { entries };
|
|
68
|
+
} catch (err) {
|
|
69
|
+
return { entries: [], error: toSessionFsError(err) };
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
rm: async ({ path, recursive, force }) => {
|
|
73
|
+
try {
|
|
74
|
+
await provider.rm(path, recursive ?? false, force ?? false);
|
|
75
|
+
return void 0;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
return toSessionFsError(err);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
rename: async ({ src, dest }) => {
|
|
81
|
+
try {
|
|
82
|
+
await provider.rename(src, dest);
|
|
83
|
+
return void 0;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
return toSessionFsError(err);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function toSessionFsError(err) {
|
|
91
|
+
const e = err;
|
|
92
|
+
const code = e.code === "ENOENT" ? "ENOENT" : "UNKNOWN";
|
|
93
|
+
return { code, message: e.message ?? String(err) };
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
createSessionFsAdapter
|
|
97
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for the Copilot SDK
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type { SessionFsProvider } from "./sessionFsProvider.js";
|
|
5
5
|
import type { SessionEvent as GeneratedSessionEvent } from "./generated/session-events.js";
|
|
6
6
|
import type { CopilotSession } from "./session.js";
|
|
7
7
|
export type SessionEvent = GeneratedSessionEvent;
|
|
8
|
-
export type {
|
|
8
|
+
export type { SessionFsProvider } from "./sessionFsProvider.js";
|
|
9
|
+
export { createSessionFsAdapter } from "./sessionFsProvider.js";
|
|
10
|
+
export type { SessionFsFileInfo } from "./sessionFsProvider.js";
|
|
9
11
|
/**
|
|
10
12
|
* Options for creating a CopilotClient
|
|
11
13
|
*/
|
|
@@ -103,12 +105,12 @@ export interface CopilotClientOptions {
|
|
|
103
105
|
* When provided, the token is passed to the CLI server via environment variable.
|
|
104
106
|
* This takes priority over other authentication methods.
|
|
105
107
|
*/
|
|
106
|
-
|
|
108
|
+
gitHubToken?: string;
|
|
107
109
|
/**
|
|
108
110
|
* Whether to use the logged-in user for authentication.
|
|
109
111
|
* When true, the CLI server will attempt to use stored OAuth tokens or gh CLI auth.
|
|
110
|
-
* When false, only explicit tokens (
|
|
111
|
-
* @default true (but defaults to false when
|
|
112
|
+
* When false, only explicit tokens (gitHubToken or environment variables) are used.
|
|
113
|
+
* @default true (but defaults to false when gitHubToken is provided)
|
|
112
114
|
*/
|
|
113
115
|
useLoggedInUser?: boolean;
|
|
114
116
|
/**
|
|
@@ -156,6 +158,15 @@ export interface CopilotClientOptions {
|
|
|
156
158
|
* instead of the server's default local filesystem storage.
|
|
157
159
|
*/
|
|
158
160
|
sessionFs?: SessionFsConfig;
|
|
161
|
+
/**
|
|
162
|
+
* Server-wide idle timeout for sessions in seconds.
|
|
163
|
+
* Sessions without activity for this duration are automatically cleaned up.
|
|
164
|
+
* Set to 0 or omit to disable (sessions live indefinitely).
|
|
165
|
+
* This option is only used when the SDK spawns the CLI process; it is ignored
|
|
166
|
+
* when connecting to an external server via {@link cliUrl}.
|
|
167
|
+
* @default undefined (disabled)
|
|
168
|
+
*/
|
|
169
|
+
sessionIdleTimeoutSeconds?: number;
|
|
159
170
|
}
|
|
160
171
|
/**
|
|
161
172
|
* Configuration for creating a session
|
|
@@ -176,6 +187,40 @@ export type ToolResultObject = {
|
|
|
176
187
|
toolTelemetry?: Record<string, unknown>;
|
|
177
188
|
};
|
|
178
189
|
export type ToolResult = string | ToolResultObject;
|
|
190
|
+
/**
|
|
191
|
+
* Content block types within an MCP CallToolResult.
|
|
192
|
+
*/
|
|
193
|
+
type McpCallToolResultTextContent = {
|
|
194
|
+
type: "text";
|
|
195
|
+
text: string;
|
|
196
|
+
};
|
|
197
|
+
type McpCallToolResultImageContent = {
|
|
198
|
+
type: "image";
|
|
199
|
+
data: string;
|
|
200
|
+
mimeType: string;
|
|
201
|
+
};
|
|
202
|
+
type McpCallToolResultResourceContent = {
|
|
203
|
+
type: "resource";
|
|
204
|
+
resource: {
|
|
205
|
+
uri: string;
|
|
206
|
+
mimeType?: string;
|
|
207
|
+
text?: string;
|
|
208
|
+
blob?: string;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
type McpCallToolResultContent = McpCallToolResultTextContent | McpCallToolResultImageContent | McpCallToolResultResourceContent;
|
|
212
|
+
/**
|
|
213
|
+
* MCP-compatible CallToolResult type. Can be passed to
|
|
214
|
+
* {@link convertMcpCallToolResult} to produce a {@link ToolResultObject}.
|
|
215
|
+
*/
|
|
216
|
+
type McpCallToolResult = {
|
|
217
|
+
content: McpCallToolResultContent[];
|
|
218
|
+
isError?: boolean;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Converts an MCP CallToolResult into the SDK's ToolResultObject format.
|
|
222
|
+
*/
|
|
223
|
+
export declare function convertMcpCallToolResult(callResult: McpCallToolResult): ToolResultObject;
|
|
179
224
|
export interface ToolInvocation {
|
|
180
225
|
sessionId: string;
|
|
181
226
|
toolCallId: string;
|
|
@@ -532,18 +577,18 @@ export type SystemMessageConfig = SystemMessageAppendConfig | SystemMessageRepla
|
|
|
532
577
|
* Permission request types from the server
|
|
533
578
|
*/
|
|
534
579
|
export interface PermissionRequest {
|
|
535
|
-
kind: "shell" | "write" | "mcp" | "read" | "url" | "custom-tool";
|
|
580
|
+
kind: "shell" | "write" | "mcp" | "read" | "url" | "custom-tool" | "memory" | "hook";
|
|
536
581
|
toolCallId?: string;
|
|
537
|
-
[key: string]: unknown;
|
|
538
582
|
}
|
|
539
|
-
import type {
|
|
540
|
-
export type PermissionRequestResult =
|
|
583
|
+
import type { PermissionDecisionRequest } from "./generated/rpc.js";
|
|
584
|
+
export type PermissionRequestResult = PermissionDecisionRequest["result"] | {
|
|
541
585
|
kind: "no-result";
|
|
542
586
|
};
|
|
543
587
|
export type PermissionHandler = (request: PermissionRequest, invocation: {
|
|
544
588
|
sessionId: string;
|
|
545
589
|
}) => Promise<PermissionRequestResult> | PermissionRequestResult;
|
|
546
590
|
export declare const approveAll: PermissionHandler;
|
|
591
|
+
export declare const defaultJoinSessionPermissionHandler: PermissionHandler;
|
|
547
592
|
/**
|
|
548
593
|
* Request for user input from the agent (enables ask_user tool)
|
|
549
594
|
*/
|
|
@@ -756,8 +801,8 @@ interface MCPServerConfigBase {
|
|
|
756
801
|
*/
|
|
757
802
|
tools: string[];
|
|
758
803
|
/**
|
|
759
|
-
* Indicates "
|
|
760
|
-
* If not specified, defaults to "
|
|
804
|
+
* Indicates the server type: "stdio" for local/subprocess servers, "http"/"sse" for remote servers.
|
|
805
|
+
* If not specified, defaults to "stdio".
|
|
761
806
|
*/
|
|
762
807
|
type?: string;
|
|
763
808
|
/**
|
|
@@ -768,7 +813,7 @@ interface MCPServerConfigBase {
|
|
|
768
813
|
/**
|
|
769
814
|
* Configuration for a local/stdio MCP server.
|
|
770
815
|
*/
|
|
771
|
-
export interface
|
|
816
|
+
export interface MCPStdioServerConfig extends MCPServerConfigBase {
|
|
772
817
|
type?: "local" | "stdio";
|
|
773
818
|
command: string;
|
|
774
819
|
args: string[];
|
|
@@ -781,7 +826,7 @@ export interface MCPLocalServerConfig extends MCPServerConfigBase {
|
|
|
781
826
|
/**
|
|
782
827
|
* Configuration for a remote MCP server (HTTP or SSE).
|
|
783
828
|
*/
|
|
784
|
-
export interface
|
|
829
|
+
export interface MCPHTTPServerConfig extends MCPServerConfigBase {
|
|
785
830
|
type: "http" | "sse";
|
|
786
831
|
/**
|
|
787
832
|
* URL of the remote server.
|
|
@@ -795,7 +840,7 @@ export interface MCPRemoteServerConfig extends MCPServerConfigBase {
|
|
|
795
840
|
/**
|
|
796
841
|
* Union type for MCP server configurations.
|
|
797
842
|
*/
|
|
798
|
-
export type MCPServerConfig =
|
|
843
|
+
export type MCPServerConfig = MCPStdioServerConfig | MCPHTTPServerConfig;
|
|
799
844
|
/**
|
|
800
845
|
* Configuration for a custom agent.
|
|
801
846
|
*/
|
|
@@ -830,6 +875,28 @@ export interface CustomAgentConfig {
|
|
|
830
875
|
* @default true
|
|
831
876
|
*/
|
|
832
877
|
infer?: boolean;
|
|
878
|
+
/**
|
|
879
|
+
* List of skill names to preload into this agent's context.
|
|
880
|
+
* When set, the full content of each listed skill is eagerly injected into
|
|
881
|
+
* the agent's context at startup. Skills are resolved by name from the
|
|
882
|
+
* session's configured skill directories (`skillDirectories`).
|
|
883
|
+
* When omitted, no skills are injected (opt-in model).
|
|
884
|
+
*/
|
|
885
|
+
skills?: string[];
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Configuration for the default agent (the built-in agent that handles
|
|
889
|
+
* turns when no custom agent is selected).
|
|
890
|
+
* Use this to control tool visibility for the default agent independently of custom sub-agents.
|
|
891
|
+
*/
|
|
892
|
+
export interface DefaultAgentConfig {
|
|
893
|
+
/**
|
|
894
|
+
* List of tool names to exclude from the default agent.
|
|
895
|
+
* These tools remain available to custom sub-agents that reference them in their `tools` array.
|
|
896
|
+
* Use this to register tools that should only be accessed via delegation to sub-agents,
|
|
897
|
+
* keeping the default agent's context clean.
|
|
898
|
+
*/
|
|
899
|
+
excludedTools?: string[];
|
|
833
900
|
}
|
|
834
901
|
/**
|
|
835
902
|
* Configuration for infinite sessions with automatic context compaction and workspace persistence.
|
|
@@ -956,6 +1023,16 @@ export interface SessionConfig {
|
|
|
956
1023
|
*/
|
|
957
1024
|
workingDirectory?: string;
|
|
958
1025
|
streaming?: boolean;
|
|
1026
|
+
/**
|
|
1027
|
+
* Include sub-agent streaming events in the event stream. When true, streaming
|
|
1028
|
+
* delta events from sub-agents (e.g., `assistant.message_delta`,
|
|
1029
|
+
* `assistant.reasoning_delta`, `assistant.streaming_delta` with `agentId` set)
|
|
1030
|
+
* are forwarded to this connection. When false, only non-streaming sub-agent
|
|
1031
|
+
* events and `subagent.*` lifecycle events are forwarded; streaming deltas from
|
|
1032
|
+
* sub-agents are suppressed.
|
|
1033
|
+
* @default true
|
|
1034
|
+
*/
|
|
1035
|
+
includeSubAgentStreamingEvents?: boolean;
|
|
959
1036
|
/**
|
|
960
1037
|
* MCP server configurations for the session.
|
|
961
1038
|
* Keys are server names, values are server configurations.
|
|
@@ -965,6 +1042,13 @@ export interface SessionConfig {
|
|
|
965
1042
|
* Custom agent configurations for the session.
|
|
966
1043
|
*/
|
|
967
1044
|
customAgents?: CustomAgentConfig[];
|
|
1045
|
+
/**
|
|
1046
|
+
* Configuration for the default agent (the built-in agent that handles
|
|
1047
|
+
* turns when no custom agent is selected).
|
|
1048
|
+
* Use `excludedTools` to hide specific tools from the default agent while keeping
|
|
1049
|
+
* them available to custom sub-agents.
|
|
1050
|
+
*/
|
|
1051
|
+
defaultAgent?: DefaultAgentConfig;
|
|
968
1052
|
/**
|
|
969
1053
|
* Name of the custom agent to activate when the session starts.
|
|
970
1054
|
* Must match the `name` of one of the agents in `customAgents`.
|
|
@@ -985,6 +1069,17 @@ export interface SessionConfig {
|
|
|
985
1069
|
* Set to `{ enabled: false }` to disable.
|
|
986
1070
|
*/
|
|
987
1071
|
infiniteSessions?: InfiniteSessionConfig;
|
|
1072
|
+
/**
|
|
1073
|
+
* GitHub token for per-session authentication.
|
|
1074
|
+
* When provided, the runtime resolves this token into a full GitHub identity
|
|
1075
|
+
* (login, Copilot plan, endpoints) and stores it on the session. This enables
|
|
1076
|
+
* multitenancy — different sessions can have different GitHub identities.
|
|
1077
|
+
*
|
|
1078
|
+
* This is independent of the client-level `gitHubToken` in {@link CopilotClientOptions},
|
|
1079
|
+
* which authenticates the CLI process itself. The session-level token determines
|
|
1080
|
+
* the identity used for content exclusion, model routing, and quota checks.
|
|
1081
|
+
*/
|
|
1082
|
+
gitHubToken?: string;
|
|
988
1083
|
/**
|
|
989
1084
|
* Optional event handler that is registered on the session before the
|
|
990
1085
|
* session.create RPC is issued. This guarantees that early events emitted
|
|
@@ -999,12 +1094,12 @@ export interface SessionConfig {
|
|
|
999
1094
|
* Supplies a handler for session filesystem operations. This takes effect
|
|
1000
1095
|
* only if {@link CopilotClientOptions.sessionFs} is configured.
|
|
1001
1096
|
*/
|
|
1002
|
-
createSessionFsHandler?: (session: CopilotSession) =>
|
|
1097
|
+
createSessionFsHandler?: (session: CopilotSession) => SessionFsProvider;
|
|
1003
1098
|
}
|
|
1004
1099
|
/**
|
|
1005
1100
|
* Configuration for resuming a session
|
|
1006
1101
|
*/
|
|
1007
|
-
export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "commands" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "modelCapabilities" | "streaming" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "onElicitationRequest" | "hooks" | "workingDirectory" | "configDir" | "enableConfigDiscovery" | "mcpServers" | "customAgents" | "agent" | "skillDirectories" | "disabledSkills" | "infiniteSessions" | "onEvent" | "createSessionFsHandler"> & {
|
|
1102
|
+
export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "commands" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "modelCapabilities" | "streaming" | "includeSubAgentStreamingEvents" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "onElicitationRequest" | "hooks" | "workingDirectory" | "configDir" | "enableConfigDiscovery" | "mcpServers" | "customAgents" | "defaultAgent" | "agent" | "skillDirectories" | "disabledSkills" | "infiniteSessions" | "gitHubToken" | "onEvent" | "createSessionFsHandler"> & {
|
|
1008
1103
|
/**
|
|
1009
1104
|
* When true, skips emitting the session.resume event.
|
|
1010
1105
|
* Useful for reconnecting to a session without triggering resume-related side effects.
|
|
@@ -1047,6 +1142,10 @@ export interface ProviderConfig {
|
|
|
1047
1142
|
*/
|
|
1048
1143
|
apiVersion?: string;
|
|
1049
1144
|
};
|
|
1145
|
+
/**
|
|
1146
|
+
* Custom HTTP headers to include in outbound provider requests.
|
|
1147
|
+
*/
|
|
1148
|
+
headers?: Record<string, string>;
|
|
1050
1149
|
}
|
|
1051
1150
|
/**
|
|
1052
1151
|
* Options for sending a message to a session
|
|
@@ -1094,6 +1193,10 @@ export interface MessageOptions {
|
|
|
1094
1193
|
* - "immediate": Send immediately
|
|
1095
1194
|
*/
|
|
1096
1195
|
mode?: "enqueue" | "immediate";
|
|
1196
|
+
/**
|
|
1197
|
+
* Custom HTTP headers to include in outbound model requests for this turn.
|
|
1198
|
+
*/
|
|
1199
|
+
requestHeaders?: Record<string, string>;
|
|
1097
1200
|
}
|
|
1098
1201
|
/**
|
|
1099
1202
|
* All possible event type strings from SessionEvent
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
import { createSessionFsAdapter } from "./sessionFsProvider.js";
|
|
2
|
+
function convertMcpCallToolResult(callResult) {
|
|
3
|
+
const textParts = [];
|
|
4
|
+
const binaryResults = [];
|
|
5
|
+
for (const block of callResult.content) {
|
|
6
|
+
switch (block.type) {
|
|
7
|
+
case "text":
|
|
8
|
+
if (typeof block.text === "string") {
|
|
9
|
+
textParts.push(block.text);
|
|
10
|
+
}
|
|
11
|
+
break;
|
|
12
|
+
case "image":
|
|
13
|
+
if (typeof block.data === "string" && block.data && typeof block.mimeType === "string") {
|
|
14
|
+
binaryResults.push({
|
|
15
|
+
data: block.data,
|
|
16
|
+
mimeType: block.mimeType,
|
|
17
|
+
type: "image"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
case "resource": {
|
|
22
|
+
if (block.resource?.text) {
|
|
23
|
+
textParts.push(block.resource.text);
|
|
24
|
+
}
|
|
25
|
+
if (block.resource?.blob) {
|
|
26
|
+
binaryResults.push({
|
|
27
|
+
data: block.resource.blob,
|
|
28
|
+
mimeType: block.resource.mimeType ?? "application/octet-stream",
|
|
29
|
+
type: "resource",
|
|
30
|
+
description: block.resource.uri
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
textResultForLlm: textParts.join("\n"),
|
|
39
|
+
resultType: callResult.isError ? "failure" : "success",
|
|
40
|
+
...binaryResults.length > 0 ? { binaryResultsForLlm: binaryResults } : {}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
1
43
|
function defineTool(name, config) {
|
|
2
44
|
return { name, ...config };
|
|
3
45
|
}
|
|
@@ -15,9 +57,15 @@ const SYSTEM_PROMPT_SECTIONS = {
|
|
|
15
57
|
description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
|
|
16
58
|
}
|
|
17
59
|
};
|
|
18
|
-
const approveAll = () => ({ kind: "
|
|
60
|
+
const approveAll = () => ({ kind: "approve-once" });
|
|
61
|
+
const defaultJoinSessionPermissionHandler = () => ({
|
|
62
|
+
kind: "no-result"
|
|
63
|
+
});
|
|
19
64
|
export {
|
|
20
65
|
SYSTEM_PROMPT_SECTIONS,
|
|
21
66
|
approveAll,
|
|
67
|
+
convertMcpCallToolResult,
|
|
68
|
+
createSessionFsAdapter,
|
|
69
|
+
defaultJoinSessionPermissionHandler,
|
|
22
70
|
defineTool
|
|
23
71
|
};
|
package/docs/agent-author.md
CHANGED
|
@@ -18,6 +18,7 @@ For user-scoped extensions (persist across all repos), add `location: "user"`.
|
|
|
18
18
|
### Step 2: Edit the extension file
|
|
19
19
|
|
|
20
20
|
Modify the generated `extension.mjs` using `edit` or `create` tools. The file must:
|
|
21
|
+
|
|
21
22
|
- Be named `extension.mjs` (only `.mjs` is supported)
|
|
22
23
|
- Use ES module syntax (`import`/`export`)
|
|
23
24
|
- Call `joinSession({ ... })`
|
|
@@ -48,6 +49,7 @@ Check that the extension loaded successfully and isn't marked as "failed".
|
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
Discovery rules:
|
|
52
|
+
|
|
51
53
|
- The CLI scans `.github/extensions/` relative to the git root
|
|
52
54
|
- It also scans the user's copilot config extensions directory
|
|
53
55
|
- Only immediate subdirectories are checked (not recursive)
|
|
@@ -62,8 +64,8 @@ Discovery rules:
|
|
|
62
64
|
import { joinSession } from "@github/copilot-sdk/extension";
|
|
63
65
|
|
|
64
66
|
await joinSession({
|
|
65
|
-
tools: [],
|
|
66
|
-
hooks: {},
|
|
67
|
+
tools: [], // Optional — custom tools
|
|
68
|
+
hooks: {}, // Optional — lifecycle hooks
|
|
67
69
|
});
|
|
68
70
|
```
|
|
69
71
|
|
|
@@ -74,9 +76,10 @@ await joinSession({
|
|
|
74
76
|
```js
|
|
75
77
|
tools: [
|
|
76
78
|
{
|
|
77
|
-
name: "tool_name",
|
|
79
|
+
name: "tool_name", // Required. Must be globally unique across all extensions.
|
|
78
80
|
description: "What it does", // Required. Shown to the agent in tool descriptions.
|
|
79
|
-
parameters: {
|
|
81
|
+
parameters: {
|
|
82
|
+
// Optional. JSON Schema for the arguments.
|
|
80
83
|
type: "object",
|
|
81
84
|
properties: {
|
|
82
85
|
arg1: { type: "string", description: "..." },
|
|
@@ -96,10 +99,11 @@ tools: [
|
|
|
96
99
|
return `Result: ${args.arg1}`;
|
|
97
100
|
},
|
|
98
101
|
},
|
|
99
|
-
]
|
|
102
|
+
];
|
|
100
103
|
```
|
|
101
104
|
|
|
102
105
|
**Constraints:**
|
|
106
|
+
|
|
103
107
|
- Tool names must be unique across ALL loaded extensions. Collisions cause the second extension to fail to load.
|
|
104
108
|
- Handler must return a string or `{ textResultForLlm: string, resultType?: string }`.
|
|
105
109
|
- Handler receives `(args, invocation)` — the second argument has `sessionId`, `toolCallId`, `toolName`.
|
|
@@ -195,6 +199,7 @@ After `joinSession()`, the returned `session` provides:
|
|
|
195
199
|
### session.send(options)
|
|
196
200
|
|
|
197
201
|
Send a message programmatically:
|
|
202
|
+
|
|
198
203
|
```js
|
|
199
204
|
await session.send({ prompt: "Analyze the test results." });
|
|
200
205
|
await session.send({
|
|
@@ -206,6 +211,7 @@ await session.send({
|
|
|
206
211
|
### session.sendAndWait(options, timeout?)
|
|
207
212
|
|
|
208
213
|
Send and block until the agent finishes (resolves on `session.idle`):
|
|
214
|
+
|
|
209
215
|
```js
|
|
210
216
|
const response = await session.sendAndWait({ prompt: "What is 2+2?" });
|
|
211
217
|
// response?.data.content contains the agent's reply
|
|
@@ -214,6 +220,7 @@ const response = await session.sendAndWait({ prompt: "What is 2+2?" });
|
|
|
214
220
|
### session.log(message, options?)
|
|
215
221
|
|
|
216
222
|
Log to the CLI timeline:
|
|
223
|
+
|
|
217
224
|
```js
|
|
218
225
|
await session.log("Extension ready");
|
|
219
226
|
await session.log("Rate limit approaching", { level: "warning" });
|
|
@@ -224,6 +231,7 @@ await session.log("Processing...", { ephemeral: true }); // transient, not persi
|
|
|
224
231
|
### session.on(eventType, handler)
|
|
225
232
|
|
|
226
233
|
Subscribe to session events. Returns an unsubscribe function.
|
|
234
|
+
|
|
227
235
|
```js
|
|
228
236
|
const unsub = session.on("tool.execution_complete", (event) => {
|
|
229
237
|
// event.data.toolName, event.data.success, event.data.result
|
|
@@ -232,16 +240,16 @@ const unsub = session.on("tool.execution_complete", (event) => {
|
|
|
232
240
|
|
|
233
241
|
### Key Event Types
|
|
234
242
|
|
|
235
|
-
| Event
|
|
236
|
-
|
|
237
|
-
| `assistant.message`
|
|
238
|
-
| `tool.execution_start`
|
|
243
|
+
| Event | Key Data Fields |
|
|
244
|
+
| ------------------------- | ------------------------------------------------------ |
|
|
245
|
+
| `assistant.message` | `content`, `messageId` |
|
|
246
|
+
| `tool.execution_start` | `toolCallId`, `toolName`, `arguments` |
|
|
239
247
|
| `tool.execution_complete` | `toolCallId`, `toolName`, `success`, `result`, `error` |
|
|
240
|
-
| `user.message`
|
|
241
|
-
| `session.idle`
|
|
242
|
-
| `session.error`
|
|
243
|
-
| `permission.requested`
|
|
244
|
-
| `session.shutdown`
|
|
248
|
+
| `user.message` | `content`, `attachments`, `source` |
|
|
249
|
+
| `session.idle` | `backgroundTasks` |
|
|
250
|
+
| `session.error` | `errorType`, `message`, `stack` |
|
|
251
|
+
| `permission.requested` | `requestId`, `permissionRequest.kind` |
|
|
252
|
+
| `session.shutdown` | `shutdownType`, `totalPremiumRequests` |
|
|
245
253
|
|
|
246
254
|
### session.workspacePath
|
|
247
255
|
|