@glbgpt/cli 0.1.0-test.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 +111 -0
- package/dist/src/auth/authClient.d.ts +32 -0
- package/dist/src/auth/authClient.js +88 -0
- package/dist/src/auth/authClient.js.map +1 -0
- package/dist/src/auth/credentialStore.d.ts +22 -0
- package/dist/src/auth/credentialStore.js +51 -0
- package/dist/src/auth/credentialStore.js.map +1 -0
- package/dist/src/auth/loginFlow.d.ts +30 -0
- package/dist/src/auth/loginFlow.js +43 -0
- package/dist/src/auth/loginFlow.js.map +1 -0
- package/dist/src/auth/loopbackServer.d.ts +41 -0
- package/dist/src/auth/loopbackServer.js +141 -0
- package/dist/src/auth/loopbackServer.js.map +1 -0
- package/dist/src/auth/token.d.ts +8 -0
- package/dist/src/auth/token.js +15 -0
- package/dist/src/auth/token.js.map +1 -0
- package/dist/src/commands/accountCommand.d.ts +2 -0
- package/dist/src/commands/accountCommand.js +56 -0
- package/dist/src/commands/accountCommand.js.map +1 -0
- package/dist/src/commands/configCommand.d.ts +4 -0
- package/dist/src/commands/configCommand.js +53 -0
- package/dist/src/commands/configCommand.js.map +1 -0
- package/dist/src/commands/execCommand.d.ts +32 -0
- package/dist/src/commands/execCommand.js +122 -0
- package/dist/src/commands/execCommand.js.map +1 -0
- package/dist/src/commands/loginCommand.d.ts +11 -0
- package/dist/src/commands/loginCommand.js +96 -0
- package/dist/src/commands/loginCommand.js.map +1 -0
- package/dist/src/commands/mediaCommand.d.ts +41 -0
- package/dist/src/commands/mediaCommand.js +277 -0
- package/dist/src/commands/mediaCommand.js.map +1 -0
- package/dist/src/config/configFile.d.ts +30 -0
- package/dist/src/config/configFile.js +54 -0
- package/dist/src/config/configFile.js.map +1 -0
- package/dist/src/config/env.d.ts +6 -0
- package/dist/src/config/env.js +24 -0
- package/dist/src/config/env.js.map +1 -0
- package/dist/src/config/paths.d.ts +6 -0
- package/dist/src/config/paths.js +16 -0
- package/dist/src/config/paths.js.map +1 -0
- package/dist/src/core/catalog.d.ts +49 -0
- package/dist/src/core/catalog.js +96 -0
- package/dist/src/core/catalog.js.map +1 -0
- package/dist/src/core/httpChatBackend.d.ts +31 -0
- package/dist/src/core/httpChatBackend.js +134 -0
- package/dist/src/core/httpChatBackend.js.map +1 -0
- package/dist/src/core/id.d.ts +2 -0
- package/dist/src/core/id.js +5 -0
- package/dist/src/core/id.js.map +1 -0
- package/dist/src/core/runChat.d.ts +28 -0
- package/dist/src/core/runChat.js +49 -0
- package/dist/src/core/runChat.js.map +1 -0
- package/dist/src/core/session.d.ts +44 -0
- package/dist/src/core/session.js +70 -0
- package/dist/src/core/session.js.map +1 -0
- package/dist/src/core/sessionStore.d.ts +39 -0
- package/dist/src/core/sessionStore.js +106 -0
- package/dist/src/core/sessionStore.js.map +1 -0
- package/dist/src/core/toolRegistry.d.ts +19 -0
- package/dist/src/core/toolRegistry.js +53 -0
- package/dist/src/core/toolRegistry.js.map +1 -0
- package/dist/src/core/tools/generateImage.d.ts +10 -0
- package/dist/src/core/tools/generateImage.js +34 -0
- package/dist/src/core/tools/generateImage.js.map +1 -0
- package/dist/src/core/turnLoop.d.ts +31 -0
- package/dist/src/core/turnLoop.js +155 -0
- package/dist/src/core/turnLoop.js.map +1 -0
- package/dist/src/core/types.d.ts +137 -0
- package/dist/src/core/types.js +9 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/exec/input.d.ts +35 -0
- package/dist/src/exec/input.js +85 -0
- package/dist/src/exec/input.js.map +1 -0
- package/dist/src/exec/output.d.ts +39 -0
- package/dist/src/exec/output.js +84 -0
- package/dist/src/exec/output.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +253 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/server.d.ts +38 -0
- package/dist/src/mcp/server.js +99 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/media/aiApiClient.d.ts +53 -0
- package/dist/src/media/aiApiClient.js +97 -0
- package/dist/src/media/aiApiClient.js.map +1 -0
- package/dist/src/media/errors.d.ts +7 -0
- package/dist/src/media/errors.js +70 -0
- package/dist/src/media/errors.js.map +1 -0
- package/dist/src/media/executor.d.ts +50 -0
- package/dist/src/media/executor.js +55 -0
- package/dist/src/media/executor.js.map +1 -0
- package/dist/src/media/generateImageTool.d.ts +19 -0
- package/dist/src/media/generateImageTool.js +120 -0
- package/dist/src/media/generateImageTool.js.map +1 -0
- package/dist/src/media/manifest.d.ts +23 -0
- package/dist/src/media/manifest.js +558 -0
- package/dist/src/media/manifest.js.map +1 -0
- package/dist/src/media/resolution.d.ts +13 -0
- package/dist/src/media/resolution.js +42 -0
- package/dist/src/media/resolution.js.map +1 -0
- package/dist/src/media/taskLedger.d.ts +17 -0
- package/dist/src/media/taskLedger.js +44 -0
- package/dist/src/media/taskLedger.js.map +1 -0
- package/dist/src/media/taskManager.d.ts +52 -0
- package/dist/src/media/taskManager.js +130 -0
- package/dist/src/media/taskManager.js.map +1 -0
- package/dist/src/media/types.d.ts +80 -0
- package/dist/src/media/types.js +15 -0
- package/dist/src/media/types.js.map +1 -0
- package/dist/src/tui/App.d.ts +34 -0
- package/dist/src/tui/App.js +540 -0
- package/dist/src/tui/App.js.map +1 -0
- package/dist/src/tui/MultilineInput.d.ts +36 -0
- package/dist/src/tui/MultilineInput.js +221 -0
- package/dist/src/tui/MultilineInput.js.map +1 -0
- package/dist/src/tui/atPopup.d.ts +21 -0
- package/dist/src/tui/atPopup.js +55 -0
- package/dist/src/tui/atPopup.js.map +1 -0
- package/dist/src/tui/attachments.d.ts +24 -0
- package/dist/src/tui/attachments.js +91 -0
- package/dist/src/tui/attachments.js.map +1 -0
- package/dist/src/tui/branding.d.ts +22 -0
- package/dist/src/tui/branding.js +119 -0
- package/dist/src/tui/branding.js.map +1 -0
- package/dist/src/tui/chatController.d.ts +188 -0
- package/dist/src/tui/chatController.js +614 -0
- package/dist/src/tui/chatController.js.map +1 -0
- package/dist/src/tui/commands.d.ts +13 -0
- package/dist/src/tui/commands.js +22 -0
- package/dist/src/tui/commands.js.map +1 -0
- package/dist/src/tui/confirmationBridge.d.ts +23 -0
- package/dist/src/tui/confirmationBridge.js +47 -0
- package/dist/src/tui/confirmationBridge.js.map +1 -0
- package/dist/src/tui/inputHistory.d.ts +7 -0
- package/dist/src/tui/inputHistory.js +64 -0
- package/dist/src/tui/inputHistory.js.map +1 -0
- package/dist/src/tui/markdown.d.ts +1 -0
- package/dist/src/tui/markdown.js +143 -0
- package/dist/src/tui/markdown.js.map +1 -0
- package/dist/src/tui/models.d.ts +30 -0
- package/dist/src/tui/models.js +54 -0
- package/dist/src/tui/models.js.map +1 -0
- package/dist/src/tui/run.d.ts +29 -0
- package/dist/src/tui/run.js +212 -0
- package/dist/src/tui/run.js.map +1 -0
- package/dist/src/tui/slashMedia.d.ts +36 -0
- package/dist/src/tui/slashMedia.js +86 -0
- package/dist/src/tui/slashMedia.js.map +1 -0
- package/dist/src/tui/visualLines.d.ts +38 -0
- package/dist/src/tui/visualLines.js +110 -0
- package/dist/src/tui/visualLines.js.map +1 -0
- package/dist/src/util/clipboardImage.d.ts +6 -0
- package/dist/src/util/clipboardImage.js +69 -0
- package/dist/src/util/clipboardImage.js.map +1 -0
- package/dist/src/util/hyperlink.d.ts +10 -0
- package/dist/src/util/hyperlink.js +33 -0
- package/dist/src/util/hyperlink.js.map +1 -0
- package/dist/src/util/imageRef.d.ts +15 -0
- package/dist/src/util/imageRef.js +46 -0
- package/dist/src/util/imageRef.js.map +1 -0
- package/dist/src/util/inlineImage.d.ts +13 -0
- package/dist/src/util/inlineImage.js +56 -0
- package/dist/src/util/inlineImage.js.map +1 -0
- package/dist/src/util/openBrowser.d.ts +5 -0
- package/dist/src/util/openBrowser.js +23 -0
- package/dist/src/util/openBrowser.js.map +1 -0
- package/dist/src/util/retry.d.ts +43 -0
- package/dist/src/util/retry.js +116 -0
- package/dist/src/util/retry.js.map +1 -0
- package/dist/src/version.d.ts +6 -0
- package/dist/src/version.js +16 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { configDir } from '../config/paths.js';
|
|
4
|
+
/** Append-only local task ledger at ~/.config/glbgpt/tasks.jsonl. */
|
|
5
|
+
export class TaskLedger {
|
|
6
|
+
file;
|
|
7
|
+
constructor(file = path.join(configDir(), 'tasks.jsonl')) {
|
|
8
|
+
this.file = file;
|
|
9
|
+
}
|
|
10
|
+
async append(rec) {
|
|
11
|
+
await fs.mkdir(path.dirname(this.file), { recursive: true });
|
|
12
|
+
await fs.appendFile(this.file, JSON.stringify(rec) + '\n', 'utf8');
|
|
13
|
+
}
|
|
14
|
+
async list(limit = 20) {
|
|
15
|
+
let text;
|
|
16
|
+
try {
|
|
17
|
+
text = await fs.readFile(this.file, 'utf8');
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
const records = text
|
|
23
|
+
.split('\n')
|
|
24
|
+
.filter((l) => l.trim())
|
|
25
|
+
.map((l) => {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(l);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.filter((r) => r !== null);
|
|
34
|
+
return records.reverse().slice(0, limit);
|
|
35
|
+
}
|
|
36
|
+
/** Resolve "last" or a task id to a record. */
|
|
37
|
+
async resolve(idOrLast) {
|
|
38
|
+
const records = await this.list(1000);
|
|
39
|
+
if (idOrLast === 'last')
|
|
40
|
+
return records[0] ?? null;
|
|
41
|
+
return records.find((r) => r.taskId === idOrLast) ?? null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=taskLedger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskLedger.js","sourceRoot":"","sources":["../../../src/media/taskLedger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAW/C,qEAAqE;AACrE,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,OAAe,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC;QAApD,SAAI,GAAJ,IAAI,CAAgD;IAAG,CAAC;IAErF,KAAK,CAAC,MAAM,CAAC,GAAe;QAC1B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE;QACnB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAG,IAAI;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAe,CAAC;YACrC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAC9C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,QAAQ,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACnD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC;IAC5D,CAAC;CACF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AiApiClient } from './aiApiClient.js';
|
|
2
|
+
export type TaskEvent = {
|
|
3
|
+
type: 'task_progress';
|
|
4
|
+
taskId: string;
|
|
5
|
+
elapsedMs: number;
|
|
6
|
+
status: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'task_done';
|
|
9
|
+
taskId: string;
|
|
10
|
+
localPath: string;
|
|
11
|
+
outputUrl: string;
|
|
12
|
+
mediaType?: number | null;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'task_failed';
|
|
15
|
+
taskId: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
};
|
|
18
|
+
export interface TaskMeta {
|
|
19
|
+
model?: string;
|
|
20
|
+
prompt?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface TaskManagerOptions {
|
|
23
|
+
outputDir: string;
|
|
24
|
+
pollMs?: number;
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** Injectable downloader (url → destPath). Defaults to fetch + write. */
|
|
27
|
+
download?: (url: string, destPath: string) => Promise<void>;
|
|
28
|
+
/** Injectable sleep (for tests). */
|
|
29
|
+
sleep?: (ms: number) => Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Polls generation tasks to completion and downloads results.
|
|
33
|
+
*
|
|
34
|
+
* `register(taskId)` returns a promise that resolves when the task finishes (done/failed/timeout) and
|
|
35
|
+
* also emits progress/done/failed events to subscribers, so the top-level command can await while the
|
|
36
|
+
* TUI reacts to the same stream.
|
|
37
|
+
*/
|
|
38
|
+
export declare class TaskManager {
|
|
39
|
+
private readonly client;
|
|
40
|
+
private readonly opts;
|
|
41
|
+
private readonly subscribers;
|
|
42
|
+
private readonly pollMs;
|
|
43
|
+
private readonly timeoutMs;
|
|
44
|
+
private readonly download;
|
|
45
|
+
private readonly sleep;
|
|
46
|
+
constructor(client: AiApiClient, opts: TaskManagerOptions);
|
|
47
|
+
subscribe(cb: (e: TaskEvent) => void): () => void;
|
|
48
|
+
/** Poll a task to completion, downloading the result on success. Resolves with the terminal event. */
|
|
49
|
+
register(taskId: string, meta?: TaskMeta): Promise<TaskEvent>;
|
|
50
|
+
private downloadResult;
|
|
51
|
+
private emit;
|
|
52
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { describeTaskFailure } from './errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Polls generation tasks to completion and downloads results.
|
|
6
|
+
*
|
|
7
|
+
* `register(taskId)` returns a promise that resolves when the task finishes (done/failed/timeout) and
|
|
8
|
+
* also emits progress/done/failed events to subscribers, so the top-level command can await while the
|
|
9
|
+
* TUI reacts to the same stream.
|
|
10
|
+
*/
|
|
11
|
+
export class TaskManager {
|
|
12
|
+
client;
|
|
13
|
+
opts;
|
|
14
|
+
subscribers = new Set();
|
|
15
|
+
pollMs;
|
|
16
|
+
timeoutMs;
|
|
17
|
+
download;
|
|
18
|
+
sleep;
|
|
19
|
+
constructor(client, opts) {
|
|
20
|
+
this.client = client;
|
|
21
|
+
this.opts = opts;
|
|
22
|
+
this.pollMs = opts.pollMs ?? 2500;
|
|
23
|
+
this.timeoutMs = opts.timeoutMs ?? 12 * 60_000;
|
|
24
|
+
this.download = opts.download ?? defaultDownload;
|
|
25
|
+
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
26
|
+
}
|
|
27
|
+
subscribe(cb) {
|
|
28
|
+
this.subscribers.add(cb);
|
|
29
|
+
return () => this.subscribers.delete(cb);
|
|
30
|
+
}
|
|
31
|
+
/** Poll a task to completion, downloading the result on success. Resolves with the terminal event. */
|
|
32
|
+
async register(taskId, meta = {}) {
|
|
33
|
+
const start = Date.now();
|
|
34
|
+
for (;;) {
|
|
35
|
+
let info;
|
|
36
|
+
try {
|
|
37
|
+
info = await this.client.getTask(taskId);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return this.emit({ type: 'task_failed', taskId, reason: err instanceof Error ? err.message : String(err) });
|
|
41
|
+
}
|
|
42
|
+
if (info.status === 'success') {
|
|
43
|
+
if (!info.outputFileUrl) {
|
|
44
|
+
return this.emit({ type: 'task_failed', taskId, reason: 'Task succeeded but returned no output URL.' });
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const localPath = await this.downloadResult(taskId, info, meta);
|
|
48
|
+
return this.emit({ type: 'task_done', taskId, localPath, outputUrl: info.outputFileUrl, mediaType: info.mediaType });
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
// A download failure must never reject register() (that would crash the TUI's fire-and-forget path).
|
|
52
|
+
return this.emit({ type: 'task_failed', taskId, reason: `Download failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (info.status === 'failed') {
|
|
56
|
+
return this.emit({ type: 'task_failed', taskId, reason: describeTaskFailure(info.errorCode, info.failedReason) });
|
|
57
|
+
}
|
|
58
|
+
// processing / pending_retry → keep waiting
|
|
59
|
+
const elapsedMs = Date.now() - start;
|
|
60
|
+
this.emit({ type: 'task_progress', taskId, elapsedMs, status: info.status });
|
|
61
|
+
if (elapsedMs >= this.timeoutMs) {
|
|
62
|
+
return this.emit({ type: 'task_failed', taskId, reason: 'Timed out waiting for the task.' });
|
|
63
|
+
}
|
|
64
|
+
await this.sleep(this.pollMs);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async downloadResult(taskId, info, meta) {
|
|
68
|
+
await fs.mkdir(this.opts.outputDir, { recursive: true });
|
|
69
|
+
const ext = extFor(info.outputFileUrl, info.mediaType);
|
|
70
|
+
const base = `glbgpt-${meta.model ?? 'image'}-${taskId.slice(0, 8)}`;
|
|
71
|
+
const dest = path.join(this.opts.outputDir, `${base}.${ext}`);
|
|
72
|
+
await this.download(info.outputFileUrl, dest);
|
|
73
|
+
// The CDN URL often lacks a real extension; correct it from the file's magic bytes.
|
|
74
|
+
const sniffed = await sniffExt(dest);
|
|
75
|
+
if (sniffed && sniffed !== ext) {
|
|
76
|
+
const corrected = path.join(this.opts.outputDir, `${base}.${sniffed}`);
|
|
77
|
+
await fs.rename(dest, corrected);
|
|
78
|
+
return corrected;
|
|
79
|
+
}
|
|
80
|
+
return dest;
|
|
81
|
+
}
|
|
82
|
+
emit(e) {
|
|
83
|
+
for (const cb of this.subscribers)
|
|
84
|
+
cb(e);
|
|
85
|
+
return e;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function extFor(url, mediaType) {
|
|
89
|
+
const m = url.split('?')[0].match(/\.([a-z0-9]{2,4})$/i);
|
|
90
|
+
if (m)
|
|
91
|
+
return m[1].toLowerCase();
|
|
92
|
+
return mediaType === 2 ? 'mp4' : 'png';
|
|
93
|
+
}
|
|
94
|
+
/** Detect a media extension from a file's magic bytes; undefined if unrecognized. */
|
|
95
|
+
async function sniffExt(filePath) {
|
|
96
|
+
let buf;
|
|
97
|
+
try {
|
|
98
|
+
const fh = await fs.open(filePath, 'r');
|
|
99
|
+
try {
|
|
100
|
+
const b = Buffer.alloc(16);
|
|
101
|
+
const { bytesRead } = await fh.read(b, 0, 16, 0);
|
|
102
|
+
buf = b.subarray(0, bytesRead);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
await fh.close();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff)
|
|
112
|
+
return 'jpg';
|
|
113
|
+
if (buf.length >= 8 && buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47)
|
|
114
|
+
return 'png';
|
|
115
|
+
if (buf.length >= 3 && buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46)
|
|
116
|
+
return 'gif';
|
|
117
|
+
if (buf.length >= 12 && buf.toString('ascii', 0, 4) === 'RIFF' && buf.toString('ascii', 8, 12) === 'WEBP')
|
|
118
|
+
return 'webp';
|
|
119
|
+
if (buf.length >= 12 && buf.toString('ascii', 4, 8) === 'ftyp')
|
|
120
|
+
return 'mp4';
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
async function defaultDownload(url, destPath) {
|
|
124
|
+
const res = await fetch(url);
|
|
125
|
+
if (!res.ok)
|
|
126
|
+
throw new Error(`Download failed (HTTP ${res.status}) for ${url}`);
|
|
127
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
128
|
+
await fs.writeFile(destPath, buf);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=taskManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskManager.js","sourceRoot":"","sources":["../../../src/media/taskManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified media generation types.
|
|
3
|
+
*
|
|
4
|
+
* Users and the model only ever see the canonical param names here; each model's per-endpoint
|
|
5
|
+
* heterogeneity lives behind {@link ModelSpec.buildBody}. Parameter values are validated against the
|
|
6
|
+
* model's declared support (competitor-style: a clear error with allowed values), not silently clamped.
|
|
7
|
+
*/
|
|
8
|
+
/** Canonical image-generation params (already normalized; images are uploaded URLs). */
|
|
9
|
+
export interface MediaGenParams {
|
|
10
|
+
prompt: string;
|
|
11
|
+
/** Canonical aspect ratio, e.g. "16:9" or "Auto". Validated per model. */
|
|
12
|
+
aspectRatio?: string;
|
|
13
|
+
/** Canonical image resolution tier: 0.5K/1K/2K/4K. Validated per model. */
|
|
14
|
+
resolution?: string;
|
|
15
|
+
/** Reference/source image URLs (local files are uploaded before this point). */
|
|
16
|
+
images?: string[];
|
|
17
|
+
/** Batch count. */
|
|
18
|
+
n?: number;
|
|
19
|
+
seed?: number;
|
|
20
|
+
negativePrompt?: string;
|
|
21
|
+
/** img2img strength 0..1. */
|
|
22
|
+
strength?: number;
|
|
23
|
+
watermark?: boolean;
|
|
24
|
+
/** Video length in seconds. */
|
|
25
|
+
duration?: number;
|
|
26
|
+
/** Generate a soundtrack (kling sound / seedance generate_audio / wan audio toggle). */
|
|
27
|
+
generateAudio?: boolean;
|
|
28
|
+
/** First frame (image-to-video). */
|
|
29
|
+
startImage?: string;
|
|
30
|
+
/** Last frame. */
|
|
31
|
+
endImage?: string;
|
|
32
|
+
}
|
|
33
|
+
/** What a model supports — drives `model show` and local validation. */
|
|
34
|
+
export interface ModelParamSupport {
|
|
35
|
+
aspectRatios?: string[];
|
|
36
|
+
resolutions?: string[];
|
|
37
|
+
/** Resolution used when the user omits it (some estimate keys require a resolution). */
|
|
38
|
+
defaultResolution?: string;
|
|
39
|
+
maxImages?: number;
|
|
40
|
+
supportsSeed?: boolean;
|
|
41
|
+
supportsNegativePrompt?: boolean;
|
|
42
|
+
supportsStrength?: boolean;
|
|
43
|
+
supportsWatermark?: boolean;
|
|
44
|
+
/** Max batch count (image n). */
|
|
45
|
+
maxCount?: number;
|
|
46
|
+
/** Supported durations in seconds (as strings, matching the model's set). */
|
|
47
|
+
durations?: string[];
|
|
48
|
+
/** Duration used when omitted (video estimate keys often depend on it). */
|
|
49
|
+
defaultDuration?: number;
|
|
50
|
+
supportsAudio?: boolean;
|
|
51
|
+
supportsStartEndFrame?: boolean;
|
|
52
|
+
/** The model cannot run text-only: a source image is required (e.g. grok-imagine-video-1.5). */
|
|
53
|
+
requiresImage?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** A curated model entry: display + routing + support + the canonical→endpoint mapping. */
|
|
56
|
+
export interface ModelSpec {
|
|
57
|
+
id: string;
|
|
58
|
+
displayName: string;
|
|
59
|
+
type: 'image' | 'video';
|
|
60
|
+
/** yanfa numeric agent id. */
|
|
61
|
+
agentId: string;
|
|
62
|
+
/** Submit endpoint path under the API base. */
|
|
63
|
+
submitPath: string;
|
|
64
|
+
/** Model string for POST /ai-api/ai/bill/estimatePrice. */
|
|
65
|
+
estimateModel: string;
|
|
66
|
+
/**
|
|
67
|
+
* Param-dependent estimate id override (e.g. t2v vs i2v catalog ids). When present it wins
|
|
68
|
+
* over {@link estimateModel} — estimate and submit MUST price the same variant.
|
|
69
|
+
*/
|
|
70
|
+
estimateModelFor?(params: MediaGenParams): string;
|
|
71
|
+
support: ModelParamSupport;
|
|
72
|
+
/** Map canonical params to this endpoint's submit body. */
|
|
73
|
+
buildBody(params: MediaGenParams): Record<string, unknown>;
|
|
74
|
+
/** Build the params object for estimatePrice (canonical → estimate params). */
|
|
75
|
+
buildEstimateParams(params: MediaGenParams): Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
/** Thrown when a param is not supported by the chosen model; message lists allowed values. */
|
|
78
|
+
export declare class ParamValidationError extends Error {
|
|
79
|
+
constructor(message: string);
|
|
80
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified media generation types.
|
|
3
|
+
*
|
|
4
|
+
* Users and the model only ever see the canonical param names here; each model's per-endpoint
|
|
5
|
+
* heterogeneity lives behind {@link ModelSpec.buildBody}. Parameter values are validated against the
|
|
6
|
+
* model's declared support (competitor-style: a clear error with allowed values), not silently clamped.
|
|
7
|
+
*/
|
|
8
|
+
/** Thrown when a param is not supported by the chosen model; message lists allowed values. */
|
|
9
|
+
export class ParamValidationError extends Error {
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'ParamValidationError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/media/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8EH,8FAA8F;AAC9F,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ChatController } from './chatController.js';
|
|
3
|
+
import type { ConfirmationBridge } from './confirmationBridge.js';
|
|
4
|
+
import type { Session } from '../core/session.js';
|
|
5
|
+
import type { SessionSummary } from '../core/sessionStore.js';
|
|
6
|
+
import type { InputHistory } from './inputHistory.js';
|
|
7
|
+
/** Session loading hooks for `/resume` (wired by run.tsx; absent in minimal test setups). */
|
|
8
|
+
export interface SessionPickerDeps {
|
|
9
|
+
listSessions: () => Promise<SessionSummary[]>;
|
|
10
|
+
loadSession: (id: string) => Promise<{
|
|
11
|
+
session: Session;
|
|
12
|
+
timeline?: unknown[];
|
|
13
|
+
} | null>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Chat TUI (phase 1). A thin view over {@link ChatController}: it renders the timeline,
|
|
17
|
+
* handles slash commands and the `/model` selector, and forwards user input to the
|
|
18
|
+
* controller. All engine behavior (turn loop, tools) lives in core.
|
|
19
|
+
*
|
|
20
|
+
* All user-facing text is English; the model replies in the user's own language.
|
|
21
|
+
*/
|
|
22
|
+
export declare function App({ controller, confirmationBridge, sessionPicker, firstRun, fetchAccountLine, inputHistory, readClipboard, }: {
|
|
23
|
+
controller: ChatController;
|
|
24
|
+
confirmationBridge?: ConfirmationBridge;
|
|
25
|
+
sessionPicker?: SessionPickerDeps;
|
|
26
|
+
/** Show the one-time command navigation (no prior sessions on disk). */
|
|
27
|
+
firstRun?: boolean;
|
|
28
|
+
/** Async plan/credits line for the welcome block (best-effort). */
|
|
29
|
+
fetchAccountLine?: () => Promise<string | null>;
|
|
30
|
+
/** Persistent ↑/↓ input recall (wired by run.tsx). */
|
|
31
|
+
inputHistory?: InputHistory;
|
|
32
|
+
/** Clipboard-image reader override (tests). */
|
|
33
|
+
readClipboard?: () => Promise<string | null>;
|
|
34
|
+
}): React.ReactElement;
|