@todoforai/tfa-summary 0.1.0 → 0.1.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/dist/cli.js +23 -54
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2880,11 +2880,6 @@ var require_websocket_server = __commonJS((exports, module) => {
|
|
|
2880
2880
|
import { parseArgs } from "node:util";
|
|
2881
2881
|
import fs from "node:fs";
|
|
2882
2882
|
|
|
2883
|
-
// ../tfa-subagent/dist/index.js
|
|
2884
|
-
import { homedir, platform } from "os";
|
|
2885
|
-
import { readFileSync } from "fs";
|
|
2886
|
-
import { join } from "path";
|
|
2887
|
-
|
|
2888
2883
|
// ../node_modules/ws/wrapper.mjs
|
|
2889
2884
|
var import_stream = __toESM(require_stream(), 1);
|
|
2890
2885
|
var import_extension = __toESM(require_extension(), 1);
|
|
@@ -2909,45 +2904,23 @@ function normalizeApiUrl(url) {
|
|
|
2909
2904
|
return `https://${url}`;
|
|
2910
2905
|
return url.replace(/\/+$/, "");
|
|
2911
2906
|
}
|
|
2912
|
-
function credentialsPath() {
|
|
2913
|
-
const home = homedir();
|
|
2914
|
-
if (platform() === "win32")
|
|
2915
|
-
return join(home, "AppData", "Roaming", "todoforai", "credentials.json");
|
|
2916
|
-
if (platform() === "darwin")
|
|
2917
|
-
return join(home, "Library", "Application Support", "todoforai", "credentials.json");
|
|
2918
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
2919
|
-
return xdg ? join(xdg, "todoforai", "credentials.json") : join(home, ".config", "todoforai", "credentials.json");
|
|
2920
|
-
}
|
|
2921
|
-
var _credsCache;
|
|
2922
|
-
function loadCredentials() {
|
|
2923
|
-
if (_credsCache !== undefined)
|
|
2924
|
-
return _credsCache;
|
|
2925
|
-
try {
|
|
2926
|
-
_credsCache = JSON.parse(readFileSync(credentialsPath(), "utf8"));
|
|
2927
|
-
} catch {
|
|
2928
|
-
_credsCache = null;
|
|
2929
|
-
}
|
|
2930
|
-
return _credsCache;
|
|
2931
|
-
}
|
|
2932
2907
|
function resolveAuth(opts = {}) {
|
|
2933
|
-
const
|
|
2934
|
-
const
|
|
2935
|
-
const apiUrl = normalizeApiUrl(opts.apiUrl || getEnv("TODOFORAI_API_URL") || credsApiUrl || DEFAULT_API_URL);
|
|
2936
|
-
const apiKey = opts.apiKey || getEnv("TODOFORAI_API_KEY") || getEnv("TODOFORAI_API_TOKEN") || creds?.apiKey || "";
|
|
2908
|
+
const apiUrl = normalizeApiUrl(opts.apiUrl || getEnv("TODOFORAI_API_URL") || DEFAULT_API_URL);
|
|
2909
|
+
const apiToken = opts.apiToken || getEnv("TODOFORAI_API_TOKEN");
|
|
2937
2910
|
const agentSettingsId = opts.agentSettingsId || getEnv("TODOFORAI_AGENT_SETTINGS_ID");
|
|
2938
|
-
if (!
|
|
2939
|
-
throw new Error("
|
|
2911
|
+
if (!apiToken)
|
|
2912
|
+
throw new Error("TODOFORAI_API_TOKEN not set (run `todoforai-bridge` to start the bridge, or pass --api-token)");
|
|
2940
2913
|
if (!agentSettingsId)
|
|
2941
2914
|
throw new Error("agent settings id required (set TODOFORAI_AGENT_SETTINGS_ID or pass --agent <id>)");
|
|
2942
|
-
const apiBase =
|
|
2943
|
-
return { apiUrl,
|
|
2915
|
+
const apiBase = apiToken.startsWith("dst_") ? "/dst/v1" : "/api/v1";
|
|
2916
|
+
return { apiUrl, apiToken, agentSettingsId, apiBase };
|
|
2944
2917
|
}
|
|
2945
|
-
async function api(path, init = {}, apiUrl,
|
|
2918
|
+
async function api(path, init = {}, apiUrl, apiToken, tabId) {
|
|
2946
2919
|
const res = await fetch(`${apiUrl}${path}`, {
|
|
2947
2920
|
...init,
|
|
2948
2921
|
headers: {
|
|
2949
2922
|
"content-type": "application/json",
|
|
2950
|
-
"x-api-key":
|
|
2923
|
+
"x-api-key": apiToken,
|
|
2951
2924
|
...tabId ? { "x-tab-id": tabId } : {},
|
|
2952
2925
|
...init.headers ?? {}
|
|
2953
2926
|
}
|
|
@@ -2999,7 +2972,7 @@ var TERMINAL = new Set([
|
|
|
2999
2972
|
]);
|
|
3000
2973
|
async function openSocket(opts) {
|
|
3001
2974
|
const wsUrl = opts.apiUrl.replace(/^http/, "ws") + "/ws/v1/frontend?tabId=" + encodeURIComponent(opts.tabId);
|
|
3002
|
-
const ws = new wrapper_default(wsUrl, [opts.
|
|
2975
|
+
const ws = new wrapper_default(wsUrl, [opts.apiToken]);
|
|
3003
2976
|
ws.on("error", (err) => process.stderr.write(`[ws error] ${err.message}
|
|
3004
2977
|
`));
|
|
3005
2978
|
await new Promise((ok, fail) => {
|
|
@@ -3023,7 +2996,6 @@ async function streamToTerminal(ws, opts = {}) {
|
|
|
3023
2996
|
return new Promise((resolve) => {
|
|
3024
2997
|
let exitCode = 0;
|
|
3025
2998
|
let result = "";
|
|
3026
|
-
let inText = false;
|
|
3027
2999
|
const finish = (code) => {
|
|
3028
3000
|
exitCode = code;
|
|
3029
3001
|
ws.close();
|
|
@@ -3040,18 +3012,14 @@ async function streamToTerminal(ws, opts = {}) {
|
|
|
3040
3012
|
if (!t)
|
|
3041
3013
|
return;
|
|
3042
3014
|
if (t === "block:message" && typeof ev.payload?.content === "string") {
|
|
3043
|
-
|
|
3044
|
-
result += ev.payload.content;
|
|
3015
|
+
result += ev.payload.content;
|
|
3045
3016
|
if (streamStdout)
|
|
3046
3017
|
process.stdout.write(ev.payload.content);
|
|
3047
3018
|
return;
|
|
3048
3019
|
}
|
|
3049
3020
|
if (t === "block:start_universal" && ev.payload?.block_type) {
|
|
3050
3021
|
const bt = ev.payload.block_type;
|
|
3051
|
-
|
|
3052
|
-
if (inText)
|
|
3053
|
-
result = "";
|
|
3054
|
-
else if (streamStdout && bt !== "REASON")
|
|
3022
|
+
if (bt !== "TEXT" && bt !== "REASON")
|
|
3055
3023
|
process.stderr.write(`
|
|
3056
3024
|
→ ${bt}
|
|
3057
3025
|
`);
|
|
@@ -3074,9 +3042,9 @@ async function streamToTerminal(ws, opts = {}) {
|
|
|
3074
3042
|
});
|
|
3075
3043
|
}
|
|
3076
3044
|
async function runTfa(spec) {
|
|
3077
|
-
const { apiUrl,
|
|
3045
|
+
const { apiUrl, apiToken, agentSettingsId, apiBase } = resolveAuth({
|
|
3078
3046
|
apiUrl: spec.apiUrl,
|
|
3079
|
-
|
|
3047
|
+
apiToken: spec.apiToken,
|
|
3080
3048
|
agentSettingsId: spec.agentSettingsId
|
|
3081
3049
|
});
|
|
3082
3050
|
const allowed = new Set(spec.allowedTools);
|
|
@@ -3088,7 +3056,7 @@ async function runTfa(spec) {
|
|
|
3088
3056
|
}
|
|
3089
3057
|
const allowTools = requested.length ? requested : spec.allowedTools;
|
|
3090
3058
|
const tabId = crypto.randomUUID();
|
|
3091
|
-
const settings = await api(`${apiBase}/agents/${agentSettingsId}`, {}, apiUrl,
|
|
3059
|
+
const settings = await api(`${apiBase}/agents/${agentSettingsId}`, {}, apiUrl, apiToken);
|
|
3092
3060
|
const patched = patchSettings(settings, {
|
|
3093
3061
|
systemMessage: spec.systemMessage,
|
|
3094
3062
|
allowTools,
|
|
@@ -3097,22 +3065,22 @@ async function runTfa(spec) {
|
|
|
3097
3065
|
});
|
|
3098
3066
|
let projectId = spec.projectId || "";
|
|
3099
3067
|
if (!projectId) {
|
|
3100
|
-
const projects = await api(`${apiBase}/projects`, {}, apiUrl,
|
|
3068
|
+
const projects = await api(`${apiBase}/projects`, {}, apiUrl, apiToken);
|
|
3101
3069
|
if (!projects?.length)
|
|
3102
3070
|
throw new Error("no project found. Pass --project <id>.");
|
|
3103
3071
|
projectId = projects[0].project?.id ?? projects[0].id;
|
|
3104
3072
|
}
|
|
3105
|
-
const ws = await openSocket({ apiUrl,
|
|
3073
|
+
const ws = await openSocket({ apiUrl, apiToken, tabId });
|
|
3106
3074
|
const visible = spec.visible === true;
|
|
3107
3075
|
const todoRes = await api(`${apiBase}/projects/${projectId}/todos`, {
|
|
3108
3076
|
method: "POST",
|
|
3109
3077
|
body: JSON.stringify({ content: spec.content, agentSettings: patched, visible })
|
|
3110
|
-
}, apiUrl,
|
|
3078
|
+
}, apiUrl, apiToken, tabId);
|
|
3111
3079
|
const todoId = todoRes.id;
|
|
3112
3080
|
await api(`${apiBase}/todos/${todoId}/subscribe`, {
|
|
3113
3081
|
method: "POST",
|
|
3114
3082
|
body: JSON.stringify({ todoId })
|
|
3115
|
-
}, apiUrl,
|
|
3083
|
+
}, apiUrl, apiToken, tabId);
|
|
3116
3084
|
process.stderr.write(`[${spec.binName}] todo=${todoId}${visible ? "" : " (hidden)"}
|
|
3117
3085
|
`);
|
|
3118
3086
|
const { exitCode, result } = await streamToTerminal(ws, { streamStdout: visible });
|
|
@@ -3137,7 +3105,7 @@ Options:
|
|
|
3137
3105
|
-v, --version Show version
|
|
3138
3106
|
|
|
3139
3107
|
Env (auto-injected by edge shell):
|
|
3140
|
-
TODOFORAI_API_URL,
|
|
3108
|
+
TODOFORAI_API_URL, TODOFORAI_API_TOKEN, TODOFORAI_AGENT_SETTINGS_ID
|
|
3141
3109
|
`);
|
|
3142
3110
|
}
|
|
3143
3111
|
async function readStdin() {
|
|
@@ -3212,16 +3180,17 @@ ${focus}
|
|
|
3212
3180
|
const content = header + sections.join(`
|
|
3213
3181
|
|
|
3214
3182
|
`);
|
|
3215
|
-
const
|
|
3183
|
+
const { exitCode } = await runTfa({
|
|
3216
3184
|
binName: "tfa-summary",
|
|
3217
3185
|
systemMessage: SUMMARIZE_SYS_PROMPT,
|
|
3218
3186
|
allowedTools: [],
|
|
3219
3187
|
content,
|
|
3220
3188
|
model: values.model,
|
|
3221
3189
|
agentSettingsId: values.agent,
|
|
3222
|
-
projectId: values.project
|
|
3190
|
+
projectId: values.project,
|
|
3191
|
+
visible: true
|
|
3223
3192
|
});
|
|
3224
|
-
process.exit(
|
|
3193
|
+
process.exit(exitCode);
|
|
3225
3194
|
}
|
|
3226
3195
|
main().catch((e) => {
|
|
3227
3196
|
console.error(`Error: ${e?.message ?? e}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@todoforai/tfa-summary",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Lightweight TODO for AI summary — summarizes files or piped input as a real TODO and streams blocks to your terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dev": "bun run src/cli.ts"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@todoforai/tfa-subagent": "
|
|
14
|
+
"@todoforai/tfa-subagent": "^0.1.1",
|
|
15
15
|
"@types/node": "^20.11.0"
|
|
16
16
|
},
|
|
17
17
|
"keywords": ["cli", "ai", "summary", "todoforai"],
|