team 0.1.1 → 0.1.2
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 +20 -5
- package/dist/ansi.d.ts +13 -0
- package/dist/ansi.js +75 -0
- package/dist/approve/approval.d.ts +11 -0
- package/dist/approve/approval.js +75 -8
- package/dist/approve/fingerprint.d.ts +15 -4
- package/dist/approve/fingerprint.js +37 -12
- package/dist/budgets/gate.d.ts +5 -4
- package/dist/budgets/gate.js +16 -12
- package/dist/budgets/readings.d.ts +51 -7
- package/dist/budgets/readings.js +106 -16
- package/dist/budgets/table.d.ts +2 -2
- package/dist/budgets/table.js +24 -11
- package/dist/commands/add.js +11 -4
- package/dist/commands/doctor.d.ts +3 -1
- package/dist/commands/doctor.js +4 -2
- package/dist/commands/down.d.ts +2 -2
- package/dist/commands/down.js +8 -1
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.js +21 -2
- package/dist/commands/status.js +3 -2
- package/dist/commands/up.d.ts +3 -1
- package/dist/commands/up.js +9 -5
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +73 -17
- package/dist/file/types.d.ts +5 -0
- package/dist/file/validate.js +31 -11
- package/dist/herdr.d.ts +4 -0
- package/dist/herdr.js +40 -11
- package/dist/launch/agent.d.ts +1 -0
- package/dist/launch/agent.js +12 -0
- package/dist/launch/deliver.d.ts +3 -1
- package/dist/launch/deliver.js +10 -1
- package/dist/launch/execute.d.ts +2 -2
- package/dist/launch/execute.js +15 -2
- package/dist/launch/rules.d.ts +4 -2
- package/dist/launch/rules.js +17 -3
- package/dist/profiles/antigravity.yaml +13 -0
- package/dist/profiles/claude-code.yaml +30 -0
- package/dist/profiles/cursor.yaml +4 -1
- package/dist/state.d.ts +7 -4
- package/dist/state.js +37 -0
- package/dist/status/statusline.js +3 -1
- package/dist/watch/check.d.ts +1 -0
- package/dist/watch/checks/budget.js +4 -1
- package/dist/watch/pass.d.ts +3 -2
- package/dist/watch/pass.js +52 -21
- package/dist/watch/screen-core.d.ts +1 -1
- package/dist/watch/screen-core.js +89 -33
- package/dist/watch/screen-data.d.ts +9 -0
- package/dist/watch/screen-file.js +25 -7
- package/dist/watch/screen.d.ts +3 -2
- package/dist/watch/screen.js +9 -4
- package/examples/team.yaml +8 -0
- package/package.json +1 -1
|
@@ -50,14 +50,16 @@ function stageOf(node) {
|
|
|
50
50
|
}
|
|
51
51
|
function ruleOf(node, ignoreCase) {
|
|
52
52
|
const entries = mapping(node, 'a rule');
|
|
53
|
-
only(entries, ['any', 'all', 'footer', 'below_last_rule', 'none_after']);
|
|
53
|
+
only(entries, ['any', 'all', 'footer', 'on_footer', 'below_last_rule', 'without_rule', 'none_after']);
|
|
54
54
|
if (entries.length === 0)
|
|
55
55
|
fail(node.line, 'a rule has no primitive');
|
|
56
56
|
const rule = {};
|
|
57
57
|
const any = optional(entries, 'any');
|
|
58
58
|
const all = optional(entries, 'all');
|
|
59
59
|
const footer = optional(entries, 'footer');
|
|
60
|
+
const onFooter = optional(entries, 'on_footer');
|
|
60
61
|
const below = optional(entries, 'below_last_rule');
|
|
62
|
+
const withoutRule = optional(entries, 'without_rule');
|
|
61
63
|
const noneAfter = optional(entries, 'none_after');
|
|
62
64
|
if (any)
|
|
63
65
|
rule.any = patternsOf(any.value, 'any', ignoreCase);
|
|
@@ -65,8 +67,12 @@ function ruleOf(node, ignoreCase) {
|
|
|
65
67
|
rule.all = patternsOf(all.value, 'all', ignoreCase);
|
|
66
68
|
if (footer)
|
|
67
69
|
rule.footer = stringOf(footer.value) ?? fail(footer.line, '"footer" must be a string');
|
|
70
|
+
if (onFooter)
|
|
71
|
+
rule.onFooter = boolOf(onFooter.value, 'on_footer');
|
|
68
72
|
if (below)
|
|
69
73
|
rule.belowLastRule = patternOf(stringOf(below.value) ?? fail(below.line, '"below_last_rule" must be a string'), ignoreCase, below.line);
|
|
74
|
+
if (withoutRule)
|
|
75
|
+
rule.withoutRule = boolOf(withoutRule.value, 'without_rule');
|
|
70
76
|
if (noneAfter)
|
|
71
77
|
rule.noneAfter = noneAfterOf(noneAfter.value, ignoreCase);
|
|
72
78
|
return rule;
|
|
@@ -116,16 +122,20 @@ function composerOf(node) {
|
|
|
116
122
|
const entries = mapping(node, 'composer');
|
|
117
123
|
const mode = required(entries, 'mode', node.line);
|
|
118
124
|
const name = stringOf(mode.value);
|
|
125
|
+
// How the CLI renders its greyed suggestions, read off the input line's styling. Optional:
|
|
126
|
+
// a composer whose suggestions plain text already names needs none of it.
|
|
127
|
+
const style = optional(entries, 'placeholder_style');
|
|
128
|
+
const placeholderStyle = style ? placeholderStyleOf(style) : undefined;
|
|
119
129
|
if (name === 'box-to-rule') {
|
|
120
|
-
only(entries, ['mode', 'prompt', 'rule', 'placeholders']);
|
|
121
|
-
return { mode: name, prompt: regexField(entries, 'prompt', node.line), rule: regexField(entries, 'rule', node.line), placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value) };
|
|
130
|
+
only(entries, ['mode', 'prompt', 'rule', 'placeholders', 'placeholder_style']);
|
|
131
|
+
return { mode: name, prompt: regexField(entries, 'prompt', node.line), rule: regexField(entries, 'rule', node.line), placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value), placeholderStyle };
|
|
122
132
|
}
|
|
123
133
|
if (name === 'status-last') {
|
|
124
|
-
only(entries, ['mode', 'status_line', 'prompt', 'placeholders']);
|
|
125
|
-
return { mode: name, statusLine: regexField(entries, 'status_line', node.line), prompt: regexField(entries, 'prompt', node.line), placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value) };
|
|
134
|
+
only(entries, ['mode', 'status_line', 'prompt', 'placeholders', 'placeholder_style']);
|
|
135
|
+
return { mode: name, statusLine: regexField(entries, 'status_line', node.line), prompt: regexField(entries, 'prompt', node.line), placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value), placeholderStyle };
|
|
126
136
|
}
|
|
127
137
|
if (name === 'status-then-one') {
|
|
128
|
-
only(entries, ['mode', 'status_line', 'prompt', 'placeholders', 'strip_suffix', 'fallback']);
|
|
138
|
+
only(entries, ['mode', 'status_line', 'prompt', 'placeholders', 'placeholder_style', 'strip_suffix', 'fallback']);
|
|
129
139
|
const suffix = optional(entries, 'strip_suffix');
|
|
130
140
|
const fallback = required(entries, 'fallback', node.line);
|
|
131
141
|
return {
|
|
@@ -133,12 +143,13 @@ function composerOf(node) {
|
|
|
133
143
|
statusLine: regexField(entries, 'status_line', node.line),
|
|
134
144
|
prompt: regexField(entries, 'prompt', node.line),
|
|
135
145
|
placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value),
|
|
146
|
+
placeholderStyle,
|
|
136
147
|
stripSuffix: suffix ? patternOf(stringOf(suffix.value) ?? fail(suffix.line, '"strip_suffix" must be a string'), false, suffix.line) : null,
|
|
137
148
|
fallback: fallbackOf(fallback.value),
|
|
138
149
|
};
|
|
139
150
|
}
|
|
140
151
|
if (name === 'two-rules-footer-below') {
|
|
141
|
-
only(entries, ['mode', 'ignore_case', 'prompt', 'rule', 'footers', 'placeholders']);
|
|
152
|
+
only(entries, ['mode', 'ignore_case', 'prompt', 'rule', 'footers', 'placeholders', 'placeholder_style']);
|
|
142
153
|
const flag = optional(entries, 'ignore_case');
|
|
143
154
|
const ignoreCase = flag ? boolOf(flag.value, 'ignore_case') : false;
|
|
144
155
|
const footers = required(entries, 'footers', node.line);
|
|
@@ -155,10 +166,17 @@ function composerOf(node) {
|
|
|
155
166
|
return patternOf(text, ignoreCase, item.line);
|
|
156
167
|
}),
|
|
157
168
|
placeholders: placeholdersOf(required(entries, 'placeholders', node.line).value),
|
|
169
|
+
placeholderStyle,
|
|
158
170
|
};
|
|
159
171
|
}
|
|
160
172
|
fail(mode.line, `"mode" must be box-to-rule, status-last, status-then-one or two-rules-footer-below`);
|
|
161
173
|
}
|
|
174
|
+
function placeholderStyleOf(entry) {
|
|
175
|
+
const text = stringOf(entry.value);
|
|
176
|
+
if (text !== 'dim')
|
|
177
|
+
fail(entry.line, '"placeholder_style" must be dim');
|
|
178
|
+
return text;
|
|
179
|
+
}
|
|
162
180
|
function fallbackOf(node) {
|
|
163
181
|
if (node.kind !== 'seq')
|
|
164
182
|
fail(node.line, '"fallback" must be a list');
|
package/dist/watch/screen.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare function classify(cli: string, lines: string[]): Screen;
|
|
|
19
19
|
export declare function classifyComposer(cli: string, lines: string[]): Screen;
|
|
20
20
|
export declare function readScreen(cli: string, screen: string | undefined): Screen;
|
|
21
21
|
/** The one line a quota figure may come from: the composer's own status row, in the pane's last
|
|
22
|
-
* 20 lines. Null for a CLI with no status line, and for
|
|
23
|
-
* dialog, a question, a trust screen, a shell or an
|
|
22
|
+
* 20 lines, read plain — a figure is never styled. Null for a CLI with no status line, and for
|
|
23
|
+
* a window that shows no status row — a dialog, a question, a trust screen, a shell or an
|
|
24
|
+
* unknown one reads no figures. */
|
|
24
25
|
export declare function statusRow(cli: string, screen: string | undefined): string | null;
|
package/dist/watch/screen.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// What a pane's visible text shows, read against the shapes of its CLI. A screen that matches no
|
|
2
2
|
// shape is "unknown": never ready, never idle, and never grounds for typing anything.
|
|
3
|
+
// The text may keep its ANSI styling, as `herdr pane read --format ansi` reads it: matching
|
|
4
|
+
// runs on the plain form, and the styling tells a greyed suggestion from typed text.
|
|
3
5
|
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { stripSgr } from "../ansi.js";
|
|
4
7
|
import { classifyLines, composeLines, statusRowOf } from "./screen-core.js";
|
|
5
8
|
import { loadScreen } from "./screen-file.js";
|
|
6
9
|
function load(name) {
|
|
@@ -13,7 +16,8 @@ const DATA = {
|
|
|
13
16
|
cursor: load('cursor'),
|
|
14
17
|
antigravity: load('antigravity'),
|
|
15
18
|
};
|
|
16
|
-
// The window every pattern sees: the pane's last 20 lines
|
|
19
|
+
// The window every pattern sees: the pane's last 20 lines. Styled lines are trimmed only past
|
|
20
|
+
// their last escape; the core trims each line's plain form for matching.
|
|
17
21
|
function windowOf(lines) {
|
|
18
22
|
return lines.map((line) => line.trimEnd()).slice(-20);
|
|
19
23
|
}
|
|
@@ -37,11 +41,12 @@ export function readScreen(cli, screen) {
|
|
|
37
41
|
return classify(cli, screen.split('\n'));
|
|
38
42
|
}
|
|
39
43
|
/** The one line a quota figure may come from: the composer's own status row, in the pane's last
|
|
40
|
-
* 20 lines. Null for a CLI with no status line, and for
|
|
41
|
-
* dialog, a question, a trust screen, a shell or an
|
|
44
|
+
* 20 lines, read plain — a figure is never styled. Null for a CLI with no status line, and for
|
|
45
|
+
* a window that shows no status row — a dialog, a question, a trust screen, a shell or an
|
|
46
|
+
* unknown one reads no figures. */
|
|
42
47
|
export function statusRow(cli, screen) {
|
|
43
48
|
const data = DATA[cli];
|
|
44
49
|
if (data === undefined || screen === undefined)
|
|
45
50
|
return null;
|
|
46
|
-
return statusRowOf(data, windowOf(screen.split('\n')));
|
|
51
|
+
return statusRowOf(data, windowOf(stripSgr(screen).split('\n')));
|
|
47
52
|
}
|
package/examples/team.yaml
CHANGED
|
@@ -49,6 +49,7 @@ seats:
|
|
|
49
49
|
label: codex
|
|
50
50
|
cli: codex
|
|
51
51
|
vendor: openai
|
|
52
|
+
account: openai-team # the seat's account, when one vendor has two; absent, its vendor
|
|
52
53
|
model: GPT Comet
|
|
53
54
|
version: "3"
|
|
54
55
|
display: GPT-3 Comet # the vendor's spelling, for the signature
|
|
@@ -74,3 +75,10 @@ seats:
|
|
|
74
75
|
version: "1"
|
|
75
76
|
launch: nimbus-claude # a launcher on the PATH, holding the account's key and endpoint
|
|
76
77
|
count: 3
|
|
78
|
+
|
|
79
|
+
budgets: # the owner's: what is budgeted, and how long a figure stays fresh
|
|
80
|
+
accounts:
|
|
81
|
+
openai-team: # the account codex-beacon spends
|
|
82
|
+
kind: subscription
|
|
83
|
+
reserve: 20% # refuse a launch on a figure inside it
|
|
84
|
+
sources: [status_line] # Codex's status line carries its weekly figure
|