@github/copilot-sdk 1.0.29 → 1.0.30-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.
@@ -0,0 +1,65 @@
1
+ import type { DecisionAnswer, DecisionContext, DecisionErrorData, DecisionErrorKind, DecisionModelInfo, DecisionsAskRequest, DecisionsAskResult, ModelsListRequest, createServerRpc } from "./generated/rpc.js";
2
+ type ServerRpc = ReturnType<typeof createServerRpc>;
3
+ /** Options shared by the decision helpers. */
4
+ export interface DecisionCallOptions {
5
+ /**
6
+ * Rejects the call with an `AbortError` as soon as the signal aborts. The
7
+ * runtime does not observe the abort: the request still finishes, or hits
8
+ * its `timeoutMs` deadline, on the runtime side.
9
+ */
10
+ signal?: AbortSignal;
11
+ }
12
+ /** Options for {@link CopilotDecisions.yesNo}. */
13
+ export interface YesNoOptions extends DecisionCallOptions {
14
+ /** Account to ask as; see `DecisionsAskRequest.selectionId`. */
15
+ selectionId?: string;
16
+ /** GitHub token to ask as; see `DecisionsAskRequest.gitHubToken`. */
17
+ gitHubToken?: string;
18
+ /** Decision model id; the runtime default when omitted. */
19
+ model?: string;
20
+ /** Probability at or above which the answer counts as yes. Defaults to 0.5. */
21
+ threshold?: number;
22
+ /** Deadline in milliseconds; see `DecisionsAskRequest.timeoutMs`. */
23
+ timeoutMs?: number;
24
+ /** Static telemetry identifier of the calling feature. */
25
+ purpose?: string;
26
+ }
27
+ /** Result of {@link CopilotDecisions.yesNo}. A refusal is never reported as "no". */
28
+ export type YesNoResult = {
29
+ refused: false;
30
+ yes: boolean;
31
+ probability: number;
32
+ } | {
33
+ refused: true;
34
+ };
35
+ /** A decisions result with its answers also indexed by question name. */
36
+ export type DecisionsAskResultWithNames = DecisionsAskResult & {
37
+ byName: Readonly<Record<string, DecisionAnswer>>;
38
+ };
39
+ /**
40
+ * Convenience wrapper over the `decisions.*` RPCs: one-off yes/no, pick-one and
41
+ * rating questions answered by Copilot decision models.
42
+ *
43
+ * @experimental
44
+ */
45
+ export declare class CopilotDecisions {
46
+ private readonly rpc;
47
+ constructor(rpc: () => ServerRpc);
48
+ /**
49
+ * The decision models the account can call: `models.list`'s `decisionModels`,
50
+ * or an empty list when the runtime does not report them (the feature is off).
51
+ */
52
+ listModels(request?: ModelsListRequest, options?: DecisionCallOptions): Promise<DecisionModelInfo[]>;
53
+ /** Asks every question in `request` and returns the answers, also indexed by name. */
54
+ ask(request: DecisionsAskRequest, options?: DecisionCallOptions): Promise<DecisionsAskResultWithNames>;
55
+ /** Asks one yes/no question about `context`, which may be plain text or a structured context. */
56
+ yesNo(question: string, context: string | DecisionContext, options?: YesNoOptions): Promise<YesNoResult>;
57
+ }
58
+ /**
59
+ * The typed failure behind a rejected `decisions.*` call, or `undefined` when
60
+ * the error did not come from one (for example an `AbortError`).
61
+ */
62
+ export declare function decisionErrorData(error: unknown): DecisionErrorData | undefined;
63
+ /** Shorthand for `decisionErrorData(error)?.kind`. */
64
+ export declare function decisionErrorKind(error: unknown): DecisionErrorKind | undefined;
65
+ export {};
@@ -0,0 +1,113 @@
1
+ import { ResponseError } from "vscode-jsonrpc/node";
2
+ class CopilotDecisions {
3
+ constructor(rpc) {
4
+ this.rpc = rpc;
5
+ }
6
+ rpc;
7
+ /**
8
+ * The decision models the account can call: `models.list`'s `decisionModels`,
9
+ * or an empty list when the runtime does not report them (the feature is off).
10
+ */
11
+ async listModels(request, options) {
12
+ const list = await withAbort(() => this.rpc().models.list(request ?? {}), options?.signal);
13
+ return list.decisionModels ?? [];
14
+ }
15
+ /** Asks every question in `request` and returns the answers, also indexed by name. */
16
+ async ask(request, options) {
17
+ const result = await withAbort(() => this.rpc().decisions.ask(request), options?.signal);
18
+ return {
19
+ ...result,
20
+ byName: Object.fromEntries(result.answers.map((answer) => [answer.name, answer]))
21
+ };
22
+ }
23
+ /** Asks one yes/no question about `context`, which may be plain text or a structured context. */
24
+ async yesNo(question, context, options) {
25
+ const threshold = options?.threshold ?? 0.5;
26
+ const result = await this.ask(
27
+ {
28
+ context: typeof context === "string" ? { kind: "text", text: context } : context,
29
+ questions: [{ kind: "boolean", name: "answer", instructions: question }],
30
+ ...options?.selectionId !== void 0 ? { selectionId: options.selectionId } : {},
31
+ ...options?.gitHubToken !== void 0 ? { gitHubToken: options.gitHubToken } : {},
32
+ ...options?.model !== void 0 ? { model: options.model } : {},
33
+ ...options?.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
34
+ ...options?.purpose !== void 0 ? { purpose: options.purpose } : {}
35
+ },
36
+ options
37
+ );
38
+ const answer = result.answers[0];
39
+ if (answer?.kind !== "boolean") {
40
+ return { refused: true };
41
+ }
42
+ return {
43
+ refused: false,
44
+ yes: answer.probability >= threshold,
45
+ probability: answer.probability
46
+ };
47
+ }
48
+ }
49
+ function decisionErrorData(error) {
50
+ if (!(error instanceof ResponseError)) {
51
+ return void 0;
52
+ }
53
+ const data = error.data;
54
+ if (typeof data !== "object" || data === null) {
55
+ return void 0;
56
+ }
57
+ const kind = data.kind;
58
+ if (typeof kind !== "string" || !DECISION_ERROR_KINDS.has(kind)) {
59
+ return void 0;
60
+ }
61
+ return data;
62
+ }
63
+ const DECISION_ERROR_KINDS = /* @__PURE__ */ new Set([
64
+ "notEnabled",
65
+ "noModel",
66
+ "unauthenticated",
67
+ "invalidRequest",
68
+ "tooLarge",
69
+ "upstreamProtocol",
70
+ "rateLimited",
71
+ "timeout",
72
+ "unavailable",
73
+ "overloaded"
74
+ ]);
75
+ function decisionErrorKind(error) {
76
+ return decisionErrorData(error)?.kind;
77
+ }
78
+ function abortError(signal) {
79
+ const reason = signal.reason;
80
+ if (reason instanceof Error && reason.name === "AbortError") {
81
+ return reason;
82
+ }
83
+ const error = new Error("The decisions call was aborted");
84
+ error.name = "AbortError";
85
+ return error;
86
+ }
87
+ function withAbort(call, signal) {
88
+ if (!signal) {
89
+ return call();
90
+ }
91
+ if (signal.aborted) {
92
+ return Promise.reject(abortError(signal));
93
+ }
94
+ return new Promise((resolve, reject) => {
95
+ const onAbort = () => reject(abortError(signal));
96
+ signal.addEventListener("abort", onAbort, { once: true });
97
+ call().then(
98
+ (value) => {
99
+ signal.removeEventListener("abort", onAbort);
100
+ resolve(value);
101
+ },
102
+ (error) => {
103
+ signal.removeEventListener("abort", onAbort);
104
+ reject(error);
105
+ }
106
+ );
107
+ });
108
+ }
109
+ export {
110
+ CopilotDecisions,
111
+ decisionErrorData,
112
+ decisionErrorKind
113
+ };