flowcollab 0.2.4 → 0.2.5
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/bin/_client.mjs +3 -0
- package/bin/pull.mjs +33 -4
- package/package.json +1 -1
package/bin/_client.mjs
CHANGED
|
@@ -76,6 +76,8 @@ export async function flowFetch(path, { method = 'GET', body } = {}) {
|
|
|
76
76
|
'content-type': 'application/json',
|
|
77
77
|
};
|
|
78
78
|
if (actingViaClaude()) headers['x-flow-acting-via'] = 'claude';
|
|
79
|
+
const proj = process.env.FLOW_PROJECT_ID || _gc.projectId || '';
|
|
80
|
+
if (proj) headers['x-flow-project'] = proj;
|
|
79
81
|
|
|
80
82
|
const res = await fetch(url, {
|
|
81
83
|
method,
|
|
@@ -96,6 +98,7 @@ export async function flowFetch(path, { method = 'GET', body } = {}) {
|
|
|
96
98
|
|
|
97
99
|
export const RESOLVED_BASE = DEFAULT_BASE;
|
|
98
100
|
export const RESOLVED_ACTOR = process.env.FLOW_DEFAULT_ASSIGNEE || _gc.actorId || '';
|
|
101
|
+
export const RESOLVED_PROJECT = process.env.FLOW_PROJECT_ID || _gc.projectId || '';
|
|
99
102
|
export function resolvedTokenDisplay() {
|
|
100
103
|
const raw = envToken();
|
|
101
104
|
if (!raw) return '(none — run `flow-login`)';
|
package/bin/pull.mjs
CHANGED
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
3. Recent timeline activity on YOUR tasks (last 5 per task)
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { flowFetch, arg, RESOLVED_ACTOR } from './_client.mjs';
|
|
16
|
-
import { existsSync, writeFileSync } from 'fs';
|
|
15
|
+
import { flowFetch, arg, RESOLVED_ACTOR, RESOLVED_PROJECT } from './_client.mjs';
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
17
|
+
import { homedir } from 'os';
|
|
17
18
|
import { join } from 'path';
|
|
18
19
|
|
|
19
20
|
// Per-status age threshold (days) before pull flags a task as aging.
|
|
@@ -92,16 +93,29 @@ function mentionRegex(assignee) {
|
|
|
92
93
|
return new RegExp(`@to:(?:${a}-claude|${a}|claude)(?=[\\s.,;:!?)\\]]|$)`, 'i');
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
async function getActiveProjectName() {
|
|
97
|
+
try {
|
|
98
|
+
const { projects } = await flowFetch('/api/flow/projects');
|
|
99
|
+
if (!projects?.length) return null;
|
|
100
|
+
if (RESOLVED_PROJECT) {
|
|
101
|
+
const match = projects.find(p => p.id === RESOLVED_PROJECT);
|
|
102
|
+
if (match) return match.name;
|
|
103
|
+
}
|
|
104
|
+
return projects[0]?.name || null;
|
|
105
|
+
} catch { return null; }
|
|
106
|
+
}
|
|
107
|
+
|
|
95
108
|
async function main() {
|
|
96
109
|
const explicit = arg('assignee');
|
|
97
110
|
const filterAssignee = explicit === 'all' ? '' : (explicit || RESOLVED_ACTOR);
|
|
98
111
|
const focusMode = arg('focus') !== undefined;
|
|
99
112
|
const filterMilestone = arg('milestone') || '';
|
|
100
113
|
|
|
101
|
-
const [tasksRes, decRes, presenceRes] = await Promise.all([
|
|
114
|
+
const [tasksRes, decRes, presenceRes, projectName] = await Promise.all([
|
|
102
115
|
flowFetch('/api/flow/tasks?limit=200'),
|
|
103
116
|
flowFetch('/api/flow/decisions'),
|
|
104
117
|
flowFetch('/api/flow/presence').catch(() => null),
|
|
118
|
+
getActiveProjectName(),
|
|
105
119
|
]);
|
|
106
120
|
|
|
107
121
|
const allTasks = tasksRes.tasks || [];
|
|
@@ -300,7 +314,8 @@ async function main() {
|
|
|
300
314
|
focusMode ? 'focus' : null,
|
|
301
315
|
].filter(Boolean).join(', ') || 'unfiltered';
|
|
302
316
|
|
|
303
|
-
|
|
317
|
+
const headerTitle = projectName ? `Flow Board — ${projectName}` : 'Flow Board';
|
|
318
|
+
out.push(`=== ${headerTitle} snapshot (${snapshotLabel}) ===`);
|
|
304
319
|
|
|
305
320
|
if (focusMode) {
|
|
306
321
|
const open = tasks.filter(t => t.status !== 'done' && t.status !== 'awaiting_direction');
|
|
@@ -385,6 +400,20 @@ async function main() {
|
|
|
385
400
|
} catch (e) {
|
|
386
401
|
process.stderr.write(`flow-pull: --sync-md failed: ${e.message}\n`);
|
|
387
402
|
}
|
|
403
|
+
|
|
404
|
+
// Write project_id to global config
|
|
405
|
+
try {
|
|
406
|
+
const { projects } = await flowFetch('/api/flow/projects');
|
|
407
|
+
const defaultProject = projects?.find(p => p.slug === 'main') || projects?.[0];
|
|
408
|
+
if (defaultProject?.id) {
|
|
409
|
+
const configPath = join(homedir(), '.flow', 'config.json');
|
|
410
|
+
let gc = {};
|
|
411
|
+
try { gc = JSON.parse(readFileSync(configPath, 'utf8')); } catch {}
|
|
412
|
+
gc.projectId = defaultProject.id;
|
|
413
|
+
writeFileSync(configPath, JSON.stringify(gc, null, 2));
|
|
414
|
+
process.stdout.write(` project_id → ~/.flow/config.json (project: ${defaultProject.slug})\n`);
|
|
415
|
+
}
|
|
416
|
+
} catch { /* non-fatal */ }
|
|
388
417
|
}
|
|
389
418
|
}
|
|
390
419
|
|