dreamteamer 0.6.0 → 0.6.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/package.json +1 -1
- package/src/cli.js +7 -1
- package/src/commit.js +12 -3
- package/src/init.js +7 -1
- package/src/server.js +7 -1
- package/src/store.js +8 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dreamteamer",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A workspace compiler for coding agents — schema-validated records as plain files over git, compiled into every harness",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Gilad Khen <giladkhen@gmail.com>",
|
package/src/cli.js
CHANGED
|
@@ -12,6 +12,12 @@ import { deriveEvents } from './events.js';
|
|
|
12
12
|
import { commitPending } from './commit.js';
|
|
13
13
|
import { Store } from './store.js';
|
|
14
14
|
|
|
15
|
+
// git calls whose failure we CATCH must not print git's own error: execFileSync forwards the
|
|
16
|
+
// child's stderr to ours unless told otherwise, so a handled "not a git repository" still
|
|
17
|
+
// reached the user's terminal. stdout stays piped because we read it.
|
|
18
|
+
const QUIET = ['ignore', 'pipe', 'ignore'];
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
const USAGE = `usage: dreamteamer <command> | dreamteamer <collection> <verb> …
|
|
16
22
|
|
|
17
23
|
commands:
|
|
@@ -230,7 +236,7 @@ export function run(argv) {
|
|
|
230
236
|
}
|
|
231
237
|
|
|
232
238
|
function tryGit(cwd, args) {
|
|
233
|
-
try { return execFileSync('git', args, { cwd }).toString().trim() || null; } catch { return null; }
|
|
239
|
+
try { return execFileSync('git', args, { cwd, stdio: QUIET }).toString().trim() || null; } catch { return null; }
|
|
234
240
|
}
|
|
235
241
|
|
|
236
242
|
function watchAndRecompile(ws) {
|
package/src/commit.js
CHANGED
|
@@ -6,6 +6,12 @@ import fs from 'node:fs';
|
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { pathToRecord } from './events.js';
|
|
8
8
|
|
|
9
|
+
// git calls whose failure we CATCH must not print git's own error: execFileSync forwards the
|
|
10
|
+
// child's stderr to ours unless told otherwise, so a handled "not a git repository" still
|
|
11
|
+
// reached the user's terminal. stdout stays piped because we read it.
|
|
12
|
+
const QUIET = ['ignore', 'pipe', 'ignore'];
|
|
13
|
+
|
|
14
|
+
|
|
9
15
|
const VERB = { A: 'add', M: 'set', D: 'rm', R: 'rename', '?': 'add' };
|
|
10
16
|
|
|
11
17
|
/** Record directories to watch, grouped by owning repo. System-stored collections are excluded:
|
|
@@ -31,7 +37,7 @@ function scopeByRepo(descriptors, only) {
|
|
|
31
37
|
* is NOT a refusal condition — committing dirty records is this verb's entire job. */
|
|
32
38
|
function inProgress(cwd) {
|
|
33
39
|
let gitDir;
|
|
34
|
-
try { gitDir = execFileSync('git', ['rev-parse', '--absolute-git-dir'], { cwd }).toString().trim(); }
|
|
40
|
+
try { gitDir = execFileSync('git', ['rev-parse', '--absolute-git-dir'], { cwd, stdio: QUIET }).toString().trim(); }
|
|
35
41
|
catch { return 'not a git repository'; }
|
|
36
42
|
for (const [marker, label] of [['MERGE_HEAD', 'merge'], ['rebase-merge', 'rebase'], ['rebase-apply', 'rebase'], ['CHERRY_PICK_HEAD', 'cherry-pick'], ['REVERT_HEAD', 'revert']]) {
|
|
37
43
|
if (fs.existsSync(path.join(gitDir, marker))) return `a ${label} is in progress`;
|
|
@@ -42,7 +48,7 @@ function inProgress(cwd) {
|
|
|
42
48
|
/** A commit on a detached HEAD is reachable only by sha. Worth saying out loud before making one;
|
|
43
49
|
* not worth refusing over, since it is sometimes exactly what someone means to do. */
|
|
44
50
|
function detached(cwd) {
|
|
45
|
-
try { return execFileSync('git', ['symbolic-ref', '--quiet', 'HEAD'], { cwd }).toString().trim() === ''; }
|
|
51
|
+
try { return execFileSync('git', ['symbolic-ref', '--quiet', 'HEAD'], { cwd, stdio: QUIET }).toString().trim() === ''; }
|
|
46
52
|
catch { return true; }
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -57,7 +63,10 @@ function sample(root, repo, dirs, descriptors) {
|
|
|
57
63
|
// `-uall` is load-bearing: by default porcelain COLLAPSES an untracked directory to a single
|
|
58
64
|
// `?? data/notes/` entry, which maps to no record — so the first records of a brand-new
|
|
59
65
|
// collection would be invisible and dt commit would report success having committed nothing.
|
|
60
|
-
|
|
66
|
+
// QUIET: the caller (cli `status`) catches a failure here so it can still print the rest of the
|
|
67
|
+
// report in a non-git folder — but git's own "fatal: not a git repository" was reaching the
|
|
68
|
+
// terminal anyway, which made a handled case look like a crash.
|
|
69
|
+
const out = execFileSync('git', ['status', '--porcelain', '-z', '-uall', '--', ...relDirs], { cwd, stdio: QUIET }).toString();
|
|
61
70
|
const chunks = out.split('\0').filter((c) => c.length > 0);
|
|
62
71
|
const rows = [];
|
|
63
72
|
for (let i = 0; i < chunks.length; i++) {
|
package/src/init.js
CHANGED
|
@@ -9,6 +9,12 @@ import { slugOrHash } from './template.js';
|
|
|
9
9
|
import { discoverModules, KINDS } from './compile.js';
|
|
10
10
|
import { Store } from './store.js';
|
|
11
11
|
|
|
12
|
+
// git calls whose failure we CATCH must not print git's own error: execFileSync forwards the
|
|
13
|
+
// child's stderr to ours unless told otherwise, so a handled "not a git repository" still
|
|
14
|
+
// reached the user's terminal. stdout stays piped because we read it.
|
|
15
|
+
const QUIET = ['ignore', 'pipe', 'ignore'];
|
|
16
|
+
|
|
17
|
+
|
|
12
18
|
const SKELETON_KINDS = ['collections', 'skills', 'agents', 'commands', 'ui-views'];
|
|
13
19
|
|
|
14
20
|
const GITIGNORE = `node_modules/
|
|
@@ -200,7 +206,7 @@ function buildClone(dest, name) {
|
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
function tryGit(cwd, args) {
|
|
203
|
-
try { return execFileSync('git', args, { cwd }).toString().trim() || null; } catch { return null; }
|
|
209
|
+
try { return execFileSync('git', args, { cwd, stdio: QUIET }).toString().trim() || null; } catch { return null; }
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
function appendMissing(file, block) {
|
package/src/server.js
CHANGED
|
@@ -16,6 +16,12 @@ import { commandsFor, recordResolver } from './record-commands.js';
|
|
|
16
16
|
import { distinctValues } from './field-values.js';
|
|
17
17
|
import { slugOrHash } from './template.js';
|
|
18
18
|
|
|
19
|
+
// git calls whose failure we CATCH must not print git's own error: execFileSync forwards the
|
|
20
|
+
// child's stderr to ours unless told otherwise, so a handled "not a git repository" still
|
|
21
|
+
// reached the user's terminal. stdout stays piped because we read it.
|
|
22
|
+
const QUIET = ['ignore', 'pipe', 'ignore'];
|
|
23
|
+
|
|
24
|
+
|
|
19
25
|
export function startServer(ws, { port = 8080, host = '127.0.0.1' } = {}) {
|
|
20
26
|
const app = express();
|
|
21
27
|
app.use(express.json({ limit: '10mb' }));
|
|
@@ -42,7 +48,7 @@ export function startServer(ws, { port = 8080, host = '127.0.0.1' } = {}) {
|
|
|
42
48
|
// so `@me` filters in ui-views resolve to the seeded user record.
|
|
43
49
|
let operatorId = null;
|
|
44
50
|
try {
|
|
45
|
-
operatorId = slugOrHash(execFileSync('git', ['config', 'user.name'], { cwd: ws.root }).toString().trim());
|
|
51
|
+
operatorId = slugOrHash(execFileSync('git', ['config', 'user.name'], { cwd: ws.root, stdio: QUIET }).toString().trim());
|
|
46
52
|
} catch { /* no git identity — @me filters simply won't narrow */ }
|
|
47
53
|
|
|
48
54
|
api.get('/info', (req, res) => {
|
package/src/store.js
CHANGED
|
@@ -12,6 +12,12 @@ import { generateId } from './template.js';
|
|
|
12
12
|
import { parseRecord, parseRecordText, patternRe, fmtAjvError, unknownFields, walk, EXT, assertSafeId } from './records.js';
|
|
13
13
|
import { normalizeRecord } from './temporal.js';
|
|
14
14
|
import { NO_RUNTIME, loadDescriptors, runtimeDir, sourceRoots as compiledSourceRoots } from './runtime.js';
|
|
15
|
+
|
|
16
|
+
// git calls whose failure we CATCH must not print git's own error: execFileSync forwards the
|
|
17
|
+
// child's stderr to ours unless told otherwise, so a handled "not a git repository" still
|
|
18
|
+
// reached the user's terminal. stdout stays piped because we read it.
|
|
19
|
+
const QUIET = ['ignore', 'pipe', 'ignore'];
|
|
20
|
+
|
|
15
21
|
export class Store {
|
|
16
22
|
constructor({ root, pkg }) {
|
|
17
23
|
this.root = root;
|
|
@@ -66,7 +72,7 @@ export class Store {
|
|
|
66
72
|
|
|
67
73
|
// current HEAD — one cheap rev-parse per cache check vs a multi-thousand-file walk
|
|
68
74
|
gitHead() {
|
|
69
|
-
try { return execFileSync('git', ['rev-parse', 'HEAD'], { cwd: this.root }).toString().trim(); } catch { return 'no-git'; }
|
|
75
|
+
try { return execFileSync('git', ['rev-parse', 'HEAD'], { cwd: this.root, stdio: QUIET }).toString().trim(); } catch { return 'no-git'; }
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
ids(collection) {
|
|
@@ -128,7 +134,7 @@ export class Store {
|
|
|
128
134
|
const relPath = path.relative(this.root, file);
|
|
129
135
|
let previousContent;
|
|
130
136
|
try {
|
|
131
|
-
previousContent = execFileSync('git', ['show', `${hash}:${relPath}`], { cwd: this.root }).toString();
|
|
137
|
+
previousContent = execFileSync('git', ['show', `${hash}:${relPath}`], { cwd: this.root, stdio: QUIET }).toString();
|
|
132
138
|
} catch {
|
|
133
139
|
throw new Error(`${collection}/${id}: no content at ${hash} for ${relPath} — nothing was reverted.`);
|
|
134
140
|
}
|