@rose42/t3-feedback 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.
- package/LICENSE +21 -0
- package/README.md +516 -0
- package/dist/bridge/attachments.d.ts +27 -0
- package/dist/bridge/attachments.js +109 -0
- package/dist/bridge/format.d.ts +70 -0
- package/dist/bridge/format.js +358 -0
- package/dist/bridge/http.d.ts +31 -0
- package/dist/bridge/http.js +169 -0
- package/dist/bridge/index.d.ts +13 -0
- package/dist/bridge/index.js +12 -0
- package/dist/bridge/parse.d.ts +16 -0
- package/dist/bridge/parse.js +82 -0
- package/dist/bridge/paths.d.ts +10 -0
- package/dist/bridge/paths.js +10 -0
- package/dist/bridge/probeThreads.d.ts +13 -0
- package/dist/bridge/probeThreads.js +66 -0
- package/dist/bridge/readSource.d.ts +8 -0
- package/dist/bridge/readSource.js +64 -0
- package/dist/bridge/sendFeedback.d.ts +99 -0
- package/dist/bridge/sendFeedback.js +417 -0
- package/dist/cli/bin.d.ts +2 -0
- package/dist/cli/bin.js +40 -0
- package/dist/cli/constants.d.ts +4 -0
- package/dist/cli/constants.js +4 -0
- package/dist/cli/detect.d.ts +17 -0
- package/dist/cli/detect.js +118 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/init.d.ts +18 -0
- package/dist/cli/init.js +165 -0
- package/dist/cli/pm.d.ts +12 -0
- package/dist/cli/pm.js +49 -0
- package/dist/cli/prompt.d.ts +2 -0
- package/dist/cli/prompt.js +19 -0
- package/dist/cli/wire/next.d.ts +8 -0
- package/dist/cli/wire/next.js +71 -0
- package/dist/cli/wire/node.d.ts +3 -0
- package/dist/cli/wire/node.js +76 -0
- package/dist/cli/wire/vite.d.ts +25 -0
- package/dist/cli/wire/vite.js +71 -0
- package/dist/client/activeThreads.d.ts +23 -0
- package/dist/client/activeThreads.js +89 -0
- package/dist/client/cropScreenshot.d.ts +39 -0
- package/dist/client/cropScreenshot.js +212 -0
- package/dist/client/customPlugins.d.ts +7 -0
- package/dist/client/customPlugins.js +38 -0
- package/dist/client/draft.d.ts +33 -0
- package/dist/client/draft.js +222 -0
- package/dist/client/index.d.ts +24 -0
- package/dist/client/index.js +20 -0
- package/dist/client/mount.d.ts +210 -0
- package/dist/client/mount.js +2408 -0
- package/dist/client/openInT3.d.ts +28 -0
- package/dist/client/openInT3.js +81 -0
- package/dist/client/readClipboardImage.d.ts +2 -0
- package/dist/client/readClipboardImage.js +2 -0
- package/dist/client/reportType.d.ts +43 -0
- package/dist/client/reportType.js +110 -0
- package/dist/client/selectBurstFrames.d.ts +21 -0
- package/dist/client/selectBurstFrames.js +101 -0
- package/dist/client/sessionThread.d.ts +26 -0
- package/dist/client/sessionThread.js +93 -0
- package/dist/client/threadPicker.d.ts +20 -0
- package/dist/client/threadPicker.js +51 -0
- package/dist/client/transport.d.ts +11 -0
- package/dist/client/transport.js +35 -0
- package/dist/client/ui/commentPanelPlugin.d.ts +46 -0
- package/dist/client/ui/commentPanelPlugin.js +126 -0
- package/dist/client/ui/defaultPlugins.d.ts +19 -0
- package/dist/client/ui/defaultPlugins.js +48 -0
- package/dist/client/ui/elementTargetChip.d.ts +64 -0
- package/dist/client/ui/elementTargetChip.js +185 -0
- package/dist/client/ui/elementTargetPanelPlugin.d.ts +43 -0
- package/dist/client/ui/elementTargetPanelPlugin.js +167 -0
- package/dist/client/ui/elementTargetPanelSession.d.ts +49 -0
- package/dist/client/ui/elementTargetPanelSession.js +279 -0
- package/dist/client/ui/elementTargetUi.d.ts +36 -0
- package/dist/client/ui/elementTargetUi.js +105 -0
- package/dist/client/ui/host.d.ts +112 -0
- package/dist/client/ui/host.js +132 -0
- package/dist/client/ui/html.d.ts +22 -0
- package/dist/client/ui/html.js +26 -0
- package/dist/client/ui/labeledPluginPreview.d.ts +8 -0
- package/dist/client/ui/labeledPluginPreview.js +71 -0
- package/dist/client/ui/resolveContributions.d.ts +13 -0
- package/dist/client/ui/resolveContributions.js +20 -0
- package/dist/client/ui/screenshotPanelPlugin.d.ts +39 -0
- package/dist/client/ui/screenshotPanelPlugin.js +212 -0
- package/dist/client/ui/screenshotPanelSession.d.ts +84 -0
- package/dist/client/ui/screenshotPanelSession.js +445 -0
- package/dist/client/ui/screenshotUi.d.ts +31 -0
- package/dist/client/ui/screenshotUi.js +130 -0
- package/dist/client/ui/shortcuts.d.ts +32 -0
- package/dist/client/ui/shortcuts.js +40 -0
- package/dist/client/ui/slots.d.ts +73 -0
- package/dist/client/ui/slots.js +112 -0
- package/dist/controls.d.ts +8 -0
- package/dist/controls.js +16 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.js +186 -0
- package/dist/types.d.ts +464 -0
- package/dist/types.js +283 -0
- package/docs/devcontainer.md +160 -0
- package/package.json +107 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
function isFeedbackEnvelope(value) {
|
|
2
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
3
|
+
}
|
|
4
|
+
/** POST body: raw envelope, or `{ envelope, threadId? }` for session reuse. */
|
|
5
|
+
export function parseFeedbackPost(body) {
|
|
6
|
+
if (!isFeedbackEnvelope(body))
|
|
7
|
+
return null;
|
|
8
|
+
const record = body;
|
|
9
|
+
if ("envelope" in record) {
|
|
10
|
+
if (!isFeedbackEnvelope(record.envelope))
|
|
11
|
+
return null;
|
|
12
|
+
const threadId = typeof record.threadId === "string" && record.threadId.trim()
|
|
13
|
+
? record.threadId.trim()
|
|
14
|
+
: undefined;
|
|
15
|
+
return threadId ? { envelope: record.envelope, threadId } : { envelope: record.envelope };
|
|
16
|
+
}
|
|
17
|
+
return { envelope: body };
|
|
18
|
+
}
|
|
19
|
+
/** Parse `?ids=a,b` from the threads probe URL. */
|
|
20
|
+
export function parseThreadProbeIds(url) {
|
|
21
|
+
try {
|
|
22
|
+
const parsed = new URL(url, "http://t3-feedback.local");
|
|
23
|
+
const raw = parsed.searchParams.get("ids") ?? "";
|
|
24
|
+
return [
|
|
25
|
+
...new Set(raw
|
|
26
|
+
.split(",")
|
|
27
|
+
.map((id) => id.trim())
|
|
28
|
+
.filter(Boolean)),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** POST body: `{ threadIds: string[] }` (also accepts singular `threadId`). */
|
|
36
|
+
export function parseSettlePost(body) {
|
|
37
|
+
if (!body || typeof body !== "object" || Array.isArray(body))
|
|
38
|
+
return null;
|
|
39
|
+
const record = body;
|
|
40
|
+
if (typeof record.threadId === "string" && record.threadId.trim()) {
|
|
41
|
+
return [record.threadId.trim()];
|
|
42
|
+
}
|
|
43
|
+
if (!Array.isArray(record.threadIds))
|
|
44
|
+
return null;
|
|
45
|
+
const ids = [
|
|
46
|
+
...new Set(record.threadIds
|
|
47
|
+
.filter((id) => typeof id === "string")
|
|
48
|
+
.map((id) => id.trim())
|
|
49
|
+
.filter(Boolean)),
|
|
50
|
+
];
|
|
51
|
+
return ids;
|
|
52
|
+
}
|
|
53
|
+
/** Parse `{ threadId, environmentId?, projectId? }` from open query string or JSON body. */
|
|
54
|
+
export function parseOpenHandoffRequest(url, body) {
|
|
55
|
+
const fromParts = (threadIdRaw, environmentIdRaw, projectIdRaw) => {
|
|
56
|
+
const threadId = typeof threadIdRaw === "string" ? threadIdRaw.trim() : "";
|
|
57
|
+
if (!threadId)
|
|
58
|
+
return null;
|
|
59
|
+
const environmentId = typeof environmentIdRaw === "string" && environmentIdRaw.trim()
|
|
60
|
+
? environmentIdRaw.trim()
|
|
61
|
+
: undefined;
|
|
62
|
+
const projectId = typeof projectIdRaw === "string" && projectIdRaw.trim() ? projectIdRaw.trim() : undefined;
|
|
63
|
+
return {
|
|
64
|
+
threadId,
|
|
65
|
+
...(environmentId ? { environmentId } : {}),
|
|
66
|
+
...(projectId ? { projectId } : {}),
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
70
|
+
const record = body;
|
|
71
|
+
const parsed = fromParts(record.threadId, record.environmentId, record.projectId);
|
|
72
|
+
if (parsed)
|
|
73
|
+
return parsed;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const parsedUrl = new URL(url, "http://t3-feedback.local");
|
|
77
|
+
return fromParts(parsedUrl.searchParams.get("threadId"), parsedUrl.searchParams.get("environmentId"), parsedUrl.searchParams.get("projectId"));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Default Vite middleware base path (also used when `basePath` is omitted). */
|
|
2
|
+
export declare const T3_FEEDBACK_API_PATH = "/__t3-feedback";
|
|
3
|
+
export declare const T3_FEEDBACK_THREADS_PATH = "/__t3-feedback/threads";
|
|
4
|
+
export declare const T3_FEEDBACK_SETTLE_PATH = "/__t3-feedback/settle";
|
|
5
|
+
export declare const T3_FEEDBACK_OPEN_PATH = "/__t3-feedback/open";
|
|
6
|
+
/** Suffixes under a host-chosen base path (e.g. `/api/t3-feedback`). */
|
|
7
|
+
export declare const T3_FEEDBACK_THREADS_SUFFIX = "/threads";
|
|
8
|
+
export declare const T3_FEEDBACK_SETTLE_SUFFIX = "/settle";
|
|
9
|
+
export declare const T3_FEEDBACK_OPEN_SUFFIX = "/open";
|
|
10
|
+
export declare const T3_FEEDBACK_SOURCE_SUFFIX = "/source";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Default Vite middleware base path (also used when `basePath` is omitted). */
|
|
2
|
+
export const T3_FEEDBACK_API_PATH = "/__t3-feedback";
|
|
3
|
+
export const T3_FEEDBACK_THREADS_PATH = "/__t3-feedback/threads";
|
|
4
|
+
export const T3_FEEDBACK_SETTLE_PATH = "/__t3-feedback/settle";
|
|
5
|
+
export const T3_FEEDBACK_OPEN_PATH = "/__t3-feedback/open";
|
|
6
|
+
/** Suffixes under a host-chosen base path (e.g. `/api/t3-feedback`). */
|
|
7
|
+
export const T3_FEEDBACK_THREADS_SUFFIX = "/threads";
|
|
8
|
+
export const T3_FEEDBACK_SETTLE_SUFFIX = "/settle";
|
|
9
|
+
export const T3_FEEDBACK_OPEN_SUFFIX = "/open";
|
|
10
|
+
export const T3_FEEDBACK_SOURCE_SUFFIX = "/source";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ThreadProbeState } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Best-effort mapping from a shell thread object to working/settled.
|
|
4
|
+
* Unknown fields leave state as `"unknown"` so the client can fall back to TTL / dismiss.
|
|
5
|
+
*/
|
|
6
|
+
export declare function inferThreadProbeState(thread: unknown): ThreadProbeState;
|
|
7
|
+
/** True when the shell thread is archived (excluded from continue pickers). */
|
|
8
|
+
export declare function isShellThreadArchived(thread: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Prefer explicit shell settle / liveness fields, then fall back to
|
|
11
|
+
* {@link inferThreadProbeState}.
|
|
12
|
+
*/
|
|
13
|
+
export declare function listItemStateFromShellThread(thread: unknown): ThreadProbeState;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort mapping from a shell thread object to working/settled.
|
|
3
|
+
* Unknown fields leave state as `"unknown"` so the client can fall back to TTL / dismiss.
|
|
4
|
+
*/
|
|
5
|
+
export function inferThreadProbeState(thread) {
|
|
6
|
+
if (!thread || typeof thread !== "object" || Array.isArray(thread))
|
|
7
|
+
return "unknown";
|
|
8
|
+
const record = thread;
|
|
9
|
+
const boolBusyKeys = ["busy", "isRunning", "running", "isGenerating"];
|
|
10
|
+
for (const key of boolBusyKeys) {
|
|
11
|
+
if (typeof record[key] === "boolean") {
|
|
12
|
+
return record[key] ? "working" : "settled";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const statusKeys = ["status", "agentStatus", "turnStatus", "runStatus", "state"];
|
|
16
|
+
for (const key of statusKeys) {
|
|
17
|
+
const raw = record[key];
|
|
18
|
+
if (typeof raw !== "string")
|
|
19
|
+
continue;
|
|
20
|
+
const value = raw.toLowerCase();
|
|
21
|
+
if (/^(idle|done|complete|completed|settled|finished|stopped|cancelled|canceled|error|failed)$/.test(value)) {
|
|
22
|
+
return "settled";
|
|
23
|
+
}
|
|
24
|
+
if (/^(running|working|active|busy|streaming|generating|in_progress|in-progress)$/.test(value)) {
|
|
25
|
+
return "working";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const nested = record.agent ?? record.turn ?? record.run;
|
|
29
|
+
if (nested && nested !== thread) {
|
|
30
|
+
const nestedState = inferThreadProbeState(nested);
|
|
31
|
+
if (nestedState !== "unknown")
|
|
32
|
+
return nestedState;
|
|
33
|
+
}
|
|
34
|
+
return "unknown";
|
|
35
|
+
}
|
|
36
|
+
/** True when the shell thread is archived (excluded from continue pickers). */
|
|
37
|
+
export function isShellThreadArchived(thread) {
|
|
38
|
+
if (!thread || typeof thread !== "object" || Array.isArray(thread))
|
|
39
|
+
return false;
|
|
40
|
+
const archivedAt = thread.archivedAt;
|
|
41
|
+
return typeof archivedAt === "string" && archivedAt.trim().length > 0;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Prefer explicit shell settle / liveness fields, then fall back to
|
|
45
|
+
* {@link inferThreadProbeState}.
|
|
46
|
+
*/
|
|
47
|
+
export function listItemStateFromShellThread(thread) {
|
|
48
|
+
if (!thread || typeof thread !== "object" || Array.isArray(thread))
|
|
49
|
+
return "unknown";
|
|
50
|
+
const record = thread;
|
|
51
|
+
if (record.settledOverride === "settled")
|
|
52
|
+
return "settled";
|
|
53
|
+
if (record.backgroundLiveness === "working")
|
|
54
|
+
return "working";
|
|
55
|
+
if (record.settledOverride !== "active" &&
|
|
56
|
+
typeof record.settledAt === "string" &&
|
|
57
|
+
record.settledAt.trim().length > 0) {
|
|
58
|
+
return "settled";
|
|
59
|
+
}
|
|
60
|
+
const inferred = inferThreadProbeState(thread);
|
|
61
|
+
if (inferred !== "unknown")
|
|
62
|
+
return inferred;
|
|
63
|
+
if (record.backgroundLiveness === "monitoring")
|
|
64
|
+
return "working";
|
|
65
|
+
return "unknown";
|
|
66
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve an app-relative source path (e.g. `app/[locale]/page.tsx`) under one
|
|
3
|
+
* of the workspace roots. Rejects path traversal and non-source extensions.
|
|
4
|
+
*/
|
|
5
|
+
export declare function readWorkspaceSourceFile(fileParam: string, workspaceRootHints: readonly string[]): Promise<{
|
|
6
|
+
absolutePath: string;
|
|
7
|
+
content: string;
|
|
8
|
+
} | null>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const ALLOWED_EXT = new Set([".tsx", ".ts", ".jsx", ".js", ".mjs", ".cjs"]);
|
|
4
|
+
/**
|
|
5
|
+
* Resolve an app-relative source path (e.g. `app/[locale]/page.tsx`) under one
|
|
6
|
+
* of the workspace roots. Rejects path traversal and non-source extensions.
|
|
7
|
+
*/
|
|
8
|
+
export async function readWorkspaceSourceFile(fileParam, workspaceRootHints) {
|
|
9
|
+
const cleaned = fileParam.replace(/\\/g, "/").replace(/^\/+/, "").trim();
|
|
10
|
+
if (!cleaned || cleaned.includes("\0") || cleaned.includes(".."))
|
|
11
|
+
return null;
|
|
12
|
+
if (path.isAbsolute(cleaned))
|
|
13
|
+
return null;
|
|
14
|
+
const ext = path.extname(cleaned);
|
|
15
|
+
if (!ALLOWED_EXT.has(ext))
|
|
16
|
+
return null;
|
|
17
|
+
// Prefer app/package sources; allow either apps/<pkg>/… or app/… (Next app cwd).
|
|
18
|
+
if (!cleaned.startsWith("app/") &&
|
|
19
|
+
!cleaned.startsWith("apps/") &&
|
|
20
|
+
!cleaned.startsWith("packages/") &&
|
|
21
|
+
!cleaned.startsWith("src/")) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
for (const root of workspaceRootHints) {
|
|
25
|
+
const absolutePath = path.resolve(root, cleaned);
|
|
26
|
+
const rootResolved = path.resolve(root);
|
|
27
|
+
if (absolutePath !== rootResolved && !absolutePath.startsWith(rootResolved + path.sep)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const content = await fs.readFile(absolutePath, "utf8");
|
|
32
|
+
return { absolutePath, content };
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// try next root (e.g. monorepo root vs apps/b2b cwd)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// When hint is a monorepo root and the file is `app/…`, try `apps/<pkg>/app/…`.
|
|
39
|
+
if (cleaned.startsWith("app/")) {
|
|
40
|
+
for (const root of workspaceRootHints) {
|
|
41
|
+
const appsDir = path.resolve(root, "apps");
|
|
42
|
+
let entries = [];
|
|
43
|
+
try {
|
|
44
|
+
entries = await fs.readdir(appsDir);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
for (const appName of entries) {
|
|
50
|
+
if (appName.startsWith("."))
|
|
51
|
+
continue;
|
|
52
|
+
const absolutePath = path.resolve(appsDir, appName, cleaned);
|
|
53
|
+
try {
|
|
54
|
+
const content = await fs.readFile(absolutePath, "utf8");
|
|
55
|
+
return { absolutePath, content };
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// continue
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { FeedbackEnvelope } from "@rose42/feedback-capture";
|
|
2
|
+
import type { FeedbackSendResult, T3FeedbackReportTypeGlyphResolved, ThreadListItem, ThreadProbeResult, ThreadSettleResult } from "../types.js";
|
|
3
|
+
import type { T3FeedbackOpenHandoff } from "../types.js";
|
|
4
|
+
export type ShellSnapshot = {
|
|
5
|
+
snapshotSequence: number;
|
|
6
|
+
projects: Array<{
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
workspaceRoot: string;
|
|
10
|
+
}>;
|
|
11
|
+
threads: Array<{
|
|
12
|
+
id: string;
|
|
13
|
+
projectId: string;
|
|
14
|
+
title: string;
|
|
15
|
+
modelSelection: {
|
|
16
|
+
instanceId: string;
|
|
17
|
+
model: string;
|
|
18
|
+
};
|
|
19
|
+
branch: string | null;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
export type T3BridgeOptions = {
|
|
24
|
+
origin: string;
|
|
25
|
+
/**
|
|
26
|
+
* Browser-facing origin for Open-in-T3 links (may differ from `origin` when
|
|
27
|
+
* the API talks to an in-container host but the browser uses localhost).
|
|
28
|
+
*/
|
|
29
|
+
openOrigin?: string;
|
|
30
|
+
/** Optional display-title prefix for newly created threads. */
|
|
31
|
+
threadTitlePrefix?: string;
|
|
32
|
+
/**
|
|
33
|
+
* When `"emoji"` or a custom map, new thread titles use emoji type prefixes
|
|
34
|
+
* instead of `Bug` / `Feedback` / `Suggestion`.
|
|
35
|
+
*/
|
|
36
|
+
reportTypeGlyph?: T3FeedbackReportTypeGlyphResolved;
|
|
37
|
+
/**
|
|
38
|
+
* Reuse this thread when it still exists in the project snapshot.
|
|
39
|
+
* Stale / missing ids create a new thread instead.
|
|
40
|
+
*/
|
|
41
|
+
threadId?: string;
|
|
42
|
+
workspaceRootHints: string[];
|
|
43
|
+
/** Optional pre-issued bearer token; otherwise `t3 auth session issue` */
|
|
44
|
+
token?: string;
|
|
45
|
+
};
|
|
46
|
+
export type ProbeThreadsOptions = Pick<T3BridgeOptions, "origin" | "workspaceRootHints" | "token">;
|
|
47
|
+
/** Clear cached environment descriptors (tests). */
|
|
48
|
+
export declare function clearT3EnvironmentIdCache(): void;
|
|
49
|
+
export type T3EnvironmentDescriptor = {
|
|
50
|
+
environmentId: string;
|
|
51
|
+
label: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Read this server's environment descriptor from the public well-known document.
|
|
55
|
+
* Cached per API origin for the process lifetime. Always use the bridge `origin`
|
|
56
|
+
* (same server that owns the thread) — never a browser-only openOrigin.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveT3Environment(apiOrigin: string): Promise<T3EnvironmentDescriptor>;
|
|
59
|
+
/** @deprecated Prefer {@link resolveT3Environment}. */
|
|
60
|
+
export declare function resolveT3EnvironmentId(apiOrigin: string): Promise<string>;
|
|
61
|
+
/**
|
|
62
|
+
* Parse JSON from a `t3 … --json` stdout blob.
|
|
63
|
+
* Newer CLIs pretty-print; older ones emit a single line (sometimes after log lines).
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseT3JsonStdout(stdout: string): unknown;
|
|
66
|
+
/** Mint a one-time browser pairing credential (`t3 auth pairing create`). */
|
|
67
|
+
export declare function issuePairingCredential(openOrigin: string): {
|
|
68
|
+
credential: string;
|
|
69
|
+
pairUrl: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Build a seamless Open-in-T3 handoff: pair URL (auto-submits) + thread deep link.
|
|
73
|
+
* Call on click so the one-time pairing token is fresh.
|
|
74
|
+
*
|
|
75
|
+
* Environment id is always read from the bridge `origin` (the server that owns
|
|
76
|
+
* the thread). Client-supplied ids are ignored — they can be stale when multiple
|
|
77
|
+
* apps share a Vite origin / sessionStorage.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createOpenHandoff(threadId: string, options: Pick<T3BridgeOptions, "origin" | "openOrigin">): Promise<T3FeedbackOpenHandoff>;
|
|
80
|
+
export declare function pickProject(projects: Array<{
|
|
81
|
+
id: string;
|
|
82
|
+
title: string;
|
|
83
|
+
workspaceRoot: string;
|
|
84
|
+
}>, hints: string[]): {
|
|
85
|
+
id: string;
|
|
86
|
+
title: string;
|
|
87
|
+
workspaceRoot: string;
|
|
88
|
+
};
|
|
89
|
+
/** Authenticate to T3 and start a turn with the feedback envelope. */
|
|
90
|
+
export declare function sendFeedbackToT3(envelope: FeedbackEnvelope, options: T3BridgeOptions): Promise<FeedbackSendResult>;
|
|
91
|
+
/** List non-archived threads for the matched T3 project (continue picker). */
|
|
92
|
+
export declare function listThreadsInT3(options: ProbeThreadsOptions): Promise<ThreadListItem[]>;
|
|
93
|
+
/** Probe working/settled state for feedback threads in the T3 shell snapshot. */
|
|
94
|
+
export declare function probeThreadsInT3(threadIds: string[], options: ProbeThreadsOptions): Promise<ThreadProbeResult[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Settle feedback threads in T3 (`thread.settle`). Missing threads are reported
|
|
97
|
+
* as `{ ok: true, skipped: true }` so dismiss can clear the local activity list.
|
|
98
|
+
*/
|
|
99
|
+
export declare function settleThreadsInT3(threadIds: string[], options: ProbeThreadsOptions): Promise<ThreadSettleResult[]>;
|