gpt-connector 0.1.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/src/asset-discovery.d.ts +9 -0
  4. package/dist/src/asset-discovery.js +73 -0
  5. package/dist/src/asset-discovery.js.map +1 -0
  6. package/dist/src/cdp.d.ts +29 -0
  7. package/dist/src/cdp.js +182 -0
  8. package/dist/src/cdp.js.map +1 -0
  9. package/dist/src/cli.d.ts +2 -0
  10. package/dist/src/cli.js +63 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/connector.d.ts +16 -0
  13. package/dist/src/connector.js +222 -0
  14. package/dist/src/connector.js.map +1 -0
  15. package/dist/src/contract.d.ts +36 -0
  16. package/dist/src/contract.js +16 -0
  17. package/dist/src/contract.js.map +1 -0
  18. package/dist/src/errors.d.ts +7 -0
  19. package/dist/src/errors.js +23 -0
  20. package/dist/src/errors.js.map +1 -0
  21. package/dist/src/index.d.ts +11 -0
  22. package/dist/src/index.js +12 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/mcp-server.d.ts +19 -0
  25. package/dist/src/mcp-server.js +96 -0
  26. package/dist/src/mcp-server.js.map +1 -0
  27. package/dist/src/mcp.d.ts +2 -0
  28. package/dist/src/mcp.js +17 -0
  29. package/dist/src/mcp.js.map +1 -0
  30. package/dist/src/model-catalog.d.ts +23 -0
  31. package/dist/src/model-catalog.js +61 -0
  32. package/dist/src/model-catalog.js.map +1 -0
  33. package/dist/src/page-bridge.d.ts +4 -0
  34. package/dist/src/page-bridge.js +364 -0
  35. package/dist/src/page-bridge.js.map +1 -0
  36. package/dist/src/redaction.d.ts +1 -0
  37. package/dist/src/redaction.js +17 -0
  38. package/dist/src/redaction.js.map +1 -0
  39. package/dist/src/runtime-evaluate.d.ts +2 -0
  40. package/dist/src/runtime-evaluate.js +14 -0
  41. package/dist/src/runtime-evaluate.js.map +1 -0
  42. package/dist/src/session-registry.d.ts +18 -0
  43. package/dist/src/session-registry.js +57 -0
  44. package/dist/src/session-registry.js.map +1 -0
  45. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kitepon-rgb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # GPT Connector
2
+
3
+ Codex開発枠から、ログイン済みChatGPT公式Web runtimeの通常Chatを呼び出すローカルconnector。
4
+
5
+ ブラウザは認証・integrity・attestation・conversation lifecycleの実行環境として使う。composer、送信button、回答DOM、React fiberは操作・参照しない。
6
+
7
+ > [!WARNING]
8
+ > consumer Chatの非公開Web runtimeとminified bundleに依存する実験的実装。OpenAIの公開・安定APIではない。bundle contractが変わった場合は`RUNTIME_DRIFT`で停止し、別方式へ自動fallbackしない。
9
+
10
+ ## 成立済み機能
11
+
12
+ - 通常Chatのone-shot送信と自動archive。
13
+ - process内opaque sessionによる複数turn継続。
14
+ - explicit closeとserver archive read-back。
15
+ - live model catalog取得。
16
+ - model/thinking effort明示選択。
17
+ - Work-only modelの除外。
18
+ - 非対応model/effortの送信前拒否。
19
+ - CLIとstdio MCP adapter。
20
+
21
+ ## 前提
22
+
23
+ - macOS
24
+ - Google Chrome
25
+ - Node.js 26以上
26
+ - pnpm 11以上
27
+ - ChatGPTへログインできるaccount
28
+
29
+ ## npm global install
30
+
31
+ ```bash
32
+ npm install --global gpt-connector
33
+ ```
34
+
35
+ 専用Chromeを起動する。通常ChromeとOracle profileは使用しない。
36
+
37
+ ```bash
38
+ open -na 'Google Chrome' --args \
39
+ --remote-debugging-port=9223 \
40
+ --user-data-dir="$HOME/.gpt-connector/browser-profile" \
41
+ --no-first-run \
42
+ --no-default-browser-check \
43
+ https://chatgpt.com/
44
+ ```
45
+
46
+ 初回だけ、開いた専用ChromeでChatGPTへ手動ログインする。connectorはpassword、cookie、tokenを読み出さない。
47
+
48
+ ## source setup
49
+
50
+ ```bash
51
+ git clone https://github.com/kitepon-rgb/gpt-connector.git
52
+ cd gpt-connector
53
+ pnpm install
54
+ pnpm check
55
+ pnpm build
56
+ ```
57
+
58
+ read-only model smoke:
59
+
60
+ ```bash
61
+ gpt-connector models --endpoint http://127.0.0.1:9223
62
+ ```
63
+
64
+ one-shot Chat smoke:
65
+
66
+ ```bash
67
+ gpt-connector chat \
68
+ --endpoint http://127.0.0.1:9223 \
69
+ --model gpt-5-6-thinking \
70
+ --effort min \
71
+ --prompt 'Reply with exactly: OK'
72
+ ```
73
+
74
+ CLIは短命processなのでone-shot専用。複数turn sessionはMCP adapterを使う。
75
+
76
+ ## Codex MCP
77
+
78
+ Codexはtrusted projectの`.codex/config.toml`を読み、stdio serverは`command`と`env`で構成できる。npm global install後は、利用するprojectへ次の設定を置く。
79
+
80
+ ```toml
81
+ [mcp_servers.gpt_connector]
82
+ command = "gpt-connector-mcp"
83
+ startup_timeout_sec = 20
84
+ tool_timeout_sec = 240
85
+ enabled = true
86
+ required = false
87
+ enabled_tools = ["chatgpt_models", "chatgpt_chat", "chatgpt_close"]
88
+
89
+ [mcp_servers.gpt_connector.env]
90
+ GPT_CONNECTOR_CDP_ENDPOINT = "http://127.0.0.1:9223"
91
+ ```
92
+
93
+ 設定の正本はOpenAI公式の[Model Context Protocol設定](https://learn.chatgpt.com/docs/extend/mcp#configure-with-configtoml)。
94
+
95
+ 1. `npm install --global gpt-connector`を実行する。
96
+ 2. 専用Chromeを起動してログインする。
97
+ 3. `.codex/config.toml`を置いたprojectで新しいCodex taskを開く。
98
+ 4. `chatgpt_models`でlive catalogを確認する。
99
+ 5. `chatgpt_chat`を呼ぶ。
100
+ 6. `keepOpen=true`でsessionを作った場合は、最後に`chatgpt_close`を呼ぶ。
101
+
102
+ MCP tools:
103
+
104
+ - `chatgpt_models`: 通常Chat model/effort一覧。
105
+ - `chatgpt_chat`: 新規またはsession継続。既定`keepOpen=false`で応答後archive。
106
+ - `chatgpt_close`: sessionをarchiveしてhandleを破棄。deleteは行わない。
107
+
108
+ ## model/effort contract
109
+
110
+ - catalogは毎回公式`/models` runtimeから取得する。
111
+ - `is_work_mode_model=true`は通常Chatから除外する。
112
+ - model未指定なら公式defaultへ委ねる。
113
+ - effort指定時はmodel指定も必須。
114
+ - effortは対象modelのlive `thinking_efforts`と完全一致させる。
115
+ - 非対応組合せをdefaultへfallbackしない。
116
+ - `serviceTier`は別軸で、初期版では指定しない。
117
+
118
+ ## session contract
119
+
120
+ - session IDはconnector生成のopaque UUID。
121
+ - server conversation IDやclient thread IDを含まない。
122
+ - sessionはMCP server process memory限定。process再起動後は継続できない。
123
+ - 同一sessionへの並行turnは`SESSION_BUSY`。
124
+ - one-shotと`chatgpt_close`はserverの`is_archived=true`をread-backしてから成功を返す。
125
+ - delete機能はない。
126
+
127
+ ## failure codes
128
+
129
+ - `AUTH_REQUIRED`
130
+ - `CDP_UNAVAILABLE`
131
+ - `RUNTIME_DRIFT`
132
+ - `MODEL_NOT_AVAILABLE`
133
+ - `EFFORT_NOT_SUPPORTED`
134
+ - `CHAT_FAILED`
135
+ - `STREAM_INCOMPLETE`
136
+ - `SESSION_NOT_FOUND`
137
+ - `SESSION_BUSY`
138
+ - `ARCHIVE_FAILED`
139
+
140
+ ## 秘密情報とログ
141
+
142
+ - cookie、authorization、access/refresh token、integrity、attestation、conduit tokenを取得・保存しない。
143
+ - CDP生dumpを保存しない。
144
+ - server conversation IDをtool resultやlogへ出さない。
145
+ - prompt/responseをconnector側でlogしない。tool resultにはrequested assistant本文だけを返す。
146
+ - `.browser-profile/`、log、temporary dumpはgit管理外。
147
+
148
+ ## architecture
149
+
150
+ ```text
151
+ Codex ──stdio MCP──> GptConnector core ──raw CDP──> ChatGPT page main world
152
+
153
+ └─ official factory
154
+ → builder
155
+ → sender
156
+ → state getter
157
+ ```
158
+
159
+ runtime roleはasset marker、function source signature、object method shape、read-only catalog probeで一意検出する。候補が0件または複数なら実行しない。
160
+
161
+ ## license
162
+
163
+ MIT
@@ -0,0 +1,9 @@
1
+ import type { CdpClient } from "./cdp.js";
2
+ export interface RuntimeAssets {
3
+ readonly coreUrl: string;
4
+ readonly conversationUrl: string;
5
+ readonly coreFingerprint: string;
6
+ readonly conversationFingerprint: string;
7
+ }
8
+ export declare function listLoadedAssetUrls(client: CdpClient): Promise<readonly string[]>;
9
+ export declare function discoverRuntimeAssets(urls: readonly string[], fetchImplementation?: typeof fetch): Promise<RuntimeAssets>;
@@ -0,0 +1,73 @@
1
+ import { createHash } from "node:crypto";
2
+ import { ConnectorError } from "./errors.js";
3
+ import { evaluateByValue } from "./runtime-evaluate.js";
4
+ const coreMarkers = [
5
+ "/f/conversation/prepare",
6
+ "conduit_token",
7
+ "completion.submit.request",
8
+ ];
9
+ const conversationMarkers = [
10
+ "contentToSend",
11
+ "allSystemHints",
12
+ "selectedSkillIds",
13
+ "build_request_params.prompt_message",
14
+ ];
15
+ function allowedAssetUrl(value) {
16
+ try {
17
+ const url = new URL(value);
18
+ return (url.protocol === "https:" &&
19
+ (url.hostname === "chatgpt.com" || url.hostname.endsWith(".oaistatic.com")) &&
20
+ url.pathname.endsWith(".js"));
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ function fingerprint(source) {
27
+ return createHash("sha256").update(source).digest("hex").slice(0, 16);
28
+ }
29
+ function findUnique(role, candidates, markers) {
30
+ const matches = candidates.filter(({ source }) => markers.every((marker) => source.includes(marker)));
31
+ if (matches.length !== 1) {
32
+ throw new ConnectorError("RUNTIME_DRIFT", `${role} assetを一意に検出できませんでした。`, { count: matches.length });
33
+ }
34
+ return matches[0];
35
+ }
36
+ export async function listLoadedAssetUrls(client) {
37
+ const expression = String.raw `(() => Array.from(new Set([
38
+ ...Array.from(document.scripts, (element) => element.src),
39
+ ...Array.from(document.head.children)
40
+ .filter((element) => element.tagName === "LINK" && element.rel === "modulepreload")
41
+ .map((element) => element.href),
42
+ ...performance.getEntriesByType("resource").map((entry) => entry.name)
43
+ ])).filter(Boolean))()`;
44
+ const raw = await evaluateByValue(client, expression);
45
+ if (!Array.isArray(raw) || raw.some((item) => typeof item !== "string")) {
46
+ throw new ConnectorError("RUNTIME_DRIFT", "loaded asset URL一覧の形式が不正です。");
47
+ }
48
+ return [...new Set(raw.filter(allowedAssetUrl))];
49
+ }
50
+ export async function discoverRuntimeAssets(urls, fetchImplementation = fetch) {
51
+ const candidates = await Promise.all(urls.map(async (url) => {
52
+ let response;
53
+ try {
54
+ response = await fetchImplementation(url);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ if (!response.ok)
60
+ return null;
61
+ return { url, source: await response.text() };
62
+ }));
63
+ const fetched = candidates.filter((candidate) => candidate !== null);
64
+ const core = findUnique("core", fetched, coreMarkers);
65
+ const conversation = findUnique("conversation", fetched, conversationMarkers);
66
+ return {
67
+ coreUrl: core.url,
68
+ conversationUrl: conversation.url,
69
+ coreFingerprint: fingerprint(core.source),
70
+ conversationFingerprint: fingerprint(conversation.source),
71
+ };
72
+ }
73
+ //# sourceMappingURL=asset-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-discovery.js","sourceRoot":"","sources":["../../src/asset-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import WebSocket from "ws";
2
+ export interface CdpTarget {
3
+ readonly id: string;
4
+ readonly type: string;
5
+ readonly url: string;
6
+ readonly webSocketDebuggerUrl: string;
7
+ }
8
+ export interface CdpEvent {
9
+ readonly method: string;
10
+ readonly params?: unknown;
11
+ }
12
+ export interface CdpSocket {
13
+ send(data: string): void;
14
+ close(): void;
15
+ on(event: "message", listener: (data: WebSocket.RawData) => void): this;
16
+ on(event: "close", listener: () => void): this;
17
+ on(event: "error", listener: (error: Error) => void): this;
18
+ }
19
+ export type CdpEventListener = (event: CdpEvent) => void;
20
+ export declare function validateCdpEndpoint(endpoint: string): URL;
21
+ export declare function discoverChatGptTarget(endpoint: string, fetchImplementation?: typeof fetch): Promise<CdpTarget>;
22
+ export declare class CdpClient {
23
+ #private;
24
+ constructor(socket: CdpSocket, defaultTimeoutMs?: number);
25
+ static connect(debuggerUrl: string, defaultTimeoutMs?: number): Promise<CdpClient>;
26
+ onEvent(listener: CdpEventListener): () => void;
27
+ call<T>(method: string, params?: unknown, timeoutMs?: number): Promise<T>;
28
+ close(): void;
29
+ }
@@ -0,0 +1,182 @@
1
+ import { EventEmitter } from "node:events";
2
+ import WebSocket from "ws";
3
+ import { ConnectorError } from "./errors.js";
4
+ const loopbackHosts = new Set(["127.0.0.1", "[::1]"]);
5
+ export function validateCdpEndpoint(endpoint) {
6
+ let url;
7
+ try {
8
+ url = new URL(endpoint);
9
+ }
10
+ catch {
11
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP endpointがURLではありません。");
12
+ }
13
+ if (url.protocol !== "http:" || !loopbackHosts.has(url.hostname)) {
14
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP endpointはloopback HTTPだけを利用できます。");
15
+ }
16
+ if (url.username !== "" || url.password !== "" || url.pathname !== "/") {
17
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP endpointの形式が不正です。");
18
+ }
19
+ return url;
20
+ }
21
+ function isCdpTarget(value) {
22
+ if (typeof value !== "object" || value === null)
23
+ return false;
24
+ const candidate = value;
25
+ return (typeof candidate.id === "string" &&
26
+ typeof candidate.type === "string" &&
27
+ typeof candidate.url === "string" &&
28
+ typeof candidate.webSocketDebuggerUrl === "string");
29
+ }
30
+ export async function discoverChatGptTarget(endpoint, fetchImplementation = fetch) {
31
+ const base = validateCdpEndpoint(endpoint);
32
+ const listUrl = new URL("/json/list", base);
33
+ let response;
34
+ try {
35
+ response = await fetchImplementation(listUrl);
36
+ }
37
+ catch {
38
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP target一覧へ接続できません。");
39
+ }
40
+ if (!response.ok) {
41
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP target一覧の取得に失敗しました。", {
42
+ status: response.status,
43
+ });
44
+ }
45
+ const raw = await response.json();
46
+ if (!Array.isArray(raw)) {
47
+ throw new ConnectorError("CDP_UNAVAILABLE", "CDP target一覧の形式が不正です。");
48
+ }
49
+ const targets = raw.filter(isCdpTarget);
50
+ const matches = targets.filter((target) => {
51
+ if (target.type !== "page")
52
+ return false;
53
+ try {
54
+ return new URL(target.url).origin === "https://chatgpt.com";
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ });
60
+ if (matches.length === 0) {
61
+ throw new ConnectorError("CDP_UNAVAILABLE", "専用ChromeにChatGPT公式page targetがありません。");
62
+ }
63
+ if (matches.length > 1) {
64
+ throw new ConnectorError("CDP_UNAVAILABLE", "ChatGPT page targetが複数あります。専用Chromeでは1tabだけ開いてください。", { count: matches.length });
65
+ }
66
+ return matches[0];
67
+ }
68
+ export class CdpClient {
69
+ #socket;
70
+ #defaultTimeoutMs;
71
+ #events = new EventEmitter();
72
+ #pending = new Map();
73
+ #sequence = 0;
74
+ #closed = false;
75
+ constructor(socket, defaultTimeoutMs = 30_000) {
76
+ this.#socket = socket;
77
+ this.#defaultTimeoutMs = defaultTimeoutMs;
78
+ socket.on("message", (data) => {
79
+ this.#handleMessage(data.toString());
80
+ });
81
+ socket.on("close", () => {
82
+ this.#failAll(new ConnectorError("CDP_UNAVAILABLE", "CDP接続が閉じられました。"));
83
+ });
84
+ socket.on("error", () => {
85
+ this.#failAll(new ConnectorError("CDP_UNAVAILABLE", "CDP接続でエラーが発生しました。"));
86
+ });
87
+ }
88
+ static async connect(debuggerUrl, defaultTimeoutMs = 30_000) {
89
+ let url;
90
+ try {
91
+ url = new URL(debuggerUrl);
92
+ }
93
+ catch {
94
+ throw new ConnectorError("CDP_UNAVAILABLE", "debugger WebSocket URLが不正です。");
95
+ }
96
+ if (url.protocol !== "ws:" || !loopbackHosts.has(url.hostname)) {
97
+ throw new ConnectorError("CDP_UNAVAILABLE", "debugger WebSocketはloopbackだけを利用できます。");
98
+ }
99
+ const socket = await new Promise((resolve, reject) => {
100
+ const candidate = new WebSocket(url, { handshakeTimeout: defaultTimeoutMs });
101
+ candidate.once("open", () => resolve(candidate));
102
+ candidate.once("error", () => {
103
+ reject(new ConnectorError("CDP_UNAVAILABLE", "CDP WebSocketへ接続できません。"));
104
+ });
105
+ });
106
+ return new CdpClient(socket, defaultTimeoutMs);
107
+ }
108
+ onEvent(listener) {
109
+ this.#events.on("event", listener);
110
+ return () => this.#events.off("event", listener);
111
+ }
112
+ call(method, params = {}, timeoutMs = this.#defaultTimeoutMs) {
113
+ if (this.#closed) {
114
+ return Promise.reject(new ConnectorError("CDP_UNAVAILABLE", "閉じたCDP接続は利用できません。"));
115
+ }
116
+ const id = ++this.#sequence;
117
+ return new Promise((resolve, reject) => {
118
+ const timeout = setTimeout(() => {
119
+ this.#pending.delete(id);
120
+ reject(new ConnectorError("CDP_UNAVAILABLE", "CDP呼出しがtimeoutしました。", {
121
+ method,
122
+ }));
123
+ }, timeoutMs);
124
+ this.#pending.set(id, {
125
+ resolve: (value) => resolve(value),
126
+ reject,
127
+ timeout,
128
+ });
129
+ this.#socket.send(JSON.stringify({ id, method, params }));
130
+ });
131
+ }
132
+ close() {
133
+ if (this.#closed)
134
+ return;
135
+ this.#closed = true;
136
+ this.#socket.close();
137
+ this.#failAll(new ConnectorError("CDP_UNAVAILABLE", "CDP接続を終了しました。"));
138
+ }
139
+ #handleMessage(raw) {
140
+ let message;
141
+ try {
142
+ message = JSON.parse(raw);
143
+ }
144
+ catch {
145
+ return;
146
+ }
147
+ if (typeof message !== "object" || message === null)
148
+ return;
149
+ const record = message;
150
+ if (typeof record.id === "number") {
151
+ const pending = this.#pending.get(record.id);
152
+ if (pending === undefined)
153
+ return;
154
+ this.#pending.delete(record.id);
155
+ clearTimeout(pending.timeout);
156
+ if (record.error !== undefined) {
157
+ pending.reject(new ConnectorError("CHAT_FAILED", "CDP methodがエラーを返しました。", {
158
+ cdpCode: record.error.code ?? null,
159
+ }));
160
+ }
161
+ else {
162
+ pending.resolve(record.result);
163
+ }
164
+ return;
165
+ }
166
+ if (typeof record.method === "string") {
167
+ this.#events.emit("event", {
168
+ method: record.method,
169
+ ...(record.params === undefined ? {} : { params: record.params }),
170
+ });
171
+ }
172
+ }
173
+ #failAll(error) {
174
+ this.#closed = true;
175
+ for (const pending of this.#pending.values()) {
176
+ clearTimeout(pending.timeout);
177
+ pending.reject(error);
178
+ }
179
+ this.#pending.clear();
180
+ }
181
+ }
182
+ //# sourceMappingURL=cdp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../src/cdp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { GptConnector } from "./connector.js";
3
+ import { ConnectorError } from "./errors.js";
4
+ function parseArgs(args) {
5
+ const [command, ...rest] = args;
6
+ const values = new Map();
7
+ for (let index = 0; index < rest.length; index += 1) {
8
+ const current = rest[index];
9
+ if (!current.startsWith("--"))
10
+ throw new Error(`不明な引数: ${current}`);
11
+ const key = current.slice(2);
12
+ const next = rest[index + 1];
13
+ if (next === undefined || next.startsWith("--"))
14
+ values.set(key, true);
15
+ else {
16
+ values.set(key, next);
17
+ index += 1;
18
+ }
19
+ }
20
+ return { command, values };
21
+ }
22
+ function stringArg(values, name) {
23
+ const value = values.get(name);
24
+ return typeof value === "string" ? value : undefined;
25
+ }
26
+ async function main() {
27
+ const { command, values } = parseArgs(process.argv.slice(2));
28
+ const endpoint = stringArg(values, "endpoint") ?? "http://127.0.0.1:9223";
29
+ const connector = await GptConnector.connect({ endpoint });
30
+ try {
31
+ if (command === "models") {
32
+ process.stdout.write(`${JSON.stringify(await connector.models(), null, 2)}\n`);
33
+ return;
34
+ }
35
+ if (command === "chat") {
36
+ const prompt = stringArg(values, "prompt");
37
+ if (prompt === undefined)
38
+ throw new Error("chatには--promptが必要です。");
39
+ const result = await connector.chat({
40
+ prompt,
41
+ model: stringArg(values, "model"),
42
+ effort: stringArg(values, "effort"),
43
+ keepOpen: false,
44
+ });
45
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
46
+ return;
47
+ }
48
+ throw new Error("usage: gpt-connector models | chat --prompt <text> [--model <id>] [--effort <id>]");
49
+ }
50
+ finally {
51
+ connector.close();
52
+ }
53
+ }
54
+ main().catch((error) => {
55
+ if (error instanceof ConnectorError) {
56
+ process.stderr.write(`${JSON.stringify({ code: error.code, message: error.message })}\n`);
57
+ }
58
+ else {
59
+ process.stderr.write(`${JSON.stringify({ code: "INVALID_INPUT", message: String(error) })}\n`);
60
+ }
61
+ process.exitCode = 1;
62
+ });
63
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type ChatInput, type ChatResult, type CloseInput, type CloseResult, type ModelCatalog } from "./contract.js";
2
+ export interface ConnectorOptions {
3
+ readonly endpoint?: string;
4
+ readonly operationTimeoutMs?: number;
5
+ readonly pollIntervalMs?: number;
6
+ }
7
+ export declare class GptConnector {
8
+ #private;
9
+ private constructor();
10
+ static connect(options?: ConnectorOptions): Promise<GptConnector>;
11
+ models(): Promise<ModelCatalog>;
12
+ chat(input: ChatInput): Promise<ChatResult>;
13
+ closeSession(input: CloseInput): Promise<CloseResult>;
14
+ close(): void;
15
+ shutdown(): Promise<void>;
16
+ }