@indianic/dialout 1.13.2 → 1.14.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/dist/ai-adapters/augment.d.ts +3 -0
- package/dist/ai-adapters/augment.d.ts.map +1 -0
- package/dist/ai-adapters/augment.js +147 -0
- package/dist/ai-adapters/augment.js.map +1 -0
- package/dist/ai-adapters/index.d.ts.map +1 -1
- package/dist/ai-adapters/index.js +2 -0
- package/dist/ai-adapters/index.js.map +1 -1
- package/dist/ai-json-tail.d.ts +26 -0
- package/dist/ai-json-tail.d.ts.map +1 -0
- package/dist/ai-json-tail.js +153 -0
- package/dist/ai-json-tail.js.map +1 -0
- package/dist/ai-session-detector.d.ts +22 -4
- package/dist/ai-session-detector.d.ts.map +1 -1
- package/dist/ai-session-detector.js +43 -6
- package/dist/ai-session-detector.js.map +1 -1
- package/dist/ai-sessions.d.ts +4 -2
- package/dist/ai-sessions.d.ts.map +1 -1
- package/dist/ai-sessions.js +24 -8
- package/dist/ai-sessions.js.map +1 -1
- package/dist/ai-transcript-locator.d.ts +74 -0
- package/dist/ai-transcript-locator.d.ts.map +1 -1
- package/dist/ai-transcript-locator.js +181 -0
- package/dist/ai-transcript-locator.js.map +1 -1
- package/dist/ai-transcript-tail.d.ts +17 -1
- package/dist/ai-transcript-tail.d.ts.map +1 -1
- package/dist/ai-transcript-tail.js.map +1 -1
- package/dist/cli-client.d.ts.map +1 -1
- package/dist/cli-client.js +1 -0
- package/dist/cli-client.js.map +1 -1
- package/dist/cli.js +96 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +21 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +28 -2
- package/dist/config.js.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.d.ts +97 -0
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.js +147 -0
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/custom-agents.test.js +155 -0
- package/node_modules/@indianic/dialout-shared/dist/index.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/index.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/index.js +11 -2
- package/node_modules/@indianic/dialout-shared/dist/kinds.d.ts +1 -1
- package/node_modules/@indianic/dialout-shared/dist/kinds.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/package.json +1 -1
- package/node_modules/@indianic/dialout-shared/src/.impeccable/hook.cache.json +1 -0
- package/node_modules/@indianic/dialout-shared/src/.omc/state/sessions/e864cc5c-dad7-49c4-8666-6d7fb2297d2a/pre-tool-advisory-throttle.json +14 -0
- package/node_modules/@indianic/dialout-shared/src/custom-agents.test.ts +185 -0
- package/node_modules/@indianic/dialout-shared/src/custom-agents.ts +198 -0
- package/node_modules/@indianic/dialout-shared/src/index.ts +5 -0
- package/node_modules/@indianic/dialout-shared/src/kinds.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AiKind } from './kinds';
|
|
2
|
+
/**
|
|
3
|
+
* A coding agent this machine's owner has declared by hand.
|
|
4
|
+
*
|
|
5
|
+
* Two cases this exists for, and one it deliberately does not cover.
|
|
6
|
+
*
|
|
7
|
+
* It covers a RENAMED BINARY — a copy of a supported CLI living under another
|
|
8
|
+
* name, where argv really is `sagent` and the detector's rules cannot see it.
|
|
9
|
+
* And it covers a supported format written somewhere we do not look.
|
|
10
|
+
*
|
|
11
|
+
* It does NOT make a genuinely new vendor readable. `kind` chooses which
|
|
12
|
+
* existing parser runs, so a custom agent must write a transcript one of the
|
|
13
|
+
* adapters already understands. There is no way around that: knowing a process
|
|
14
|
+
* is an agent tells you nothing about how to read its conversation.
|
|
15
|
+
*
|
|
16
|
+
* Worth being clear about what is NOT needed here: a shell alias, function or
|
|
17
|
+
* wrapper script needs no entry at all. `sagent() { claude "$@"; }` runs a
|
|
18
|
+
* process whose argv is `claude`, and findAgentInPane walks descendants, so it
|
|
19
|
+
* is already detected. Only a renamed binary is invisible.
|
|
20
|
+
*
|
|
21
|
+
* ---
|
|
22
|
+
*
|
|
23
|
+
* MACHINE-LOCAL BY DESIGN. These live in ~/.dialout/config.json and are never
|
|
24
|
+
* accepted from the server.
|
|
25
|
+
*
|
|
26
|
+
* The agent runs as the user, with the user's full read access, and it streams
|
|
27
|
+
* whatever it is pointed at into a chat. A server-supplied path would therefore
|
|
28
|
+
* be a file-read primitive: point it at ~/.ssh/id_rsa or a .env and the
|
|
29
|
+
* contents leave the machine. Keeping the declaration on the machine means
|
|
30
|
+
* compromising a web account cannot turn every agent into a file reader — the
|
|
31
|
+
* same reasoning that keeps the ws-server bound to 127.0.0.1 and filters every
|
|
32
|
+
* value interpolated into the cowork rc block.
|
|
33
|
+
*
|
|
34
|
+
* The validation below is the second line of defence, not the first.
|
|
35
|
+
*/
|
|
36
|
+
export interface CustomAgent {
|
|
37
|
+
/** The command name as the process table shows it, e.g. 'sagent'. */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Which existing adapter reads this agent's transcript. */
|
|
40
|
+
kind: AiKind;
|
|
41
|
+
/** Where the transcript lives; see expandTranscript for the placeholders. */
|
|
42
|
+
transcript: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const AI_KINDS: readonly AiKind[];
|
|
45
|
+
export declare function isAiKind(value: unknown): value is AiKind;
|
|
46
|
+
/** The placeholders expandTranscript understands. Anything else is a typo worth reporting. */
|
|
47
|
+
export declare const TRANSCRIPT_VARS: readonly ["home", "cwd", "tty", "pid"];
|
|
48
|
+
export type CustomAgentParse = {
|
|
49
|
+
ok: true;
|
|
50
|
+
agent: CustomAgent;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
error: string;
|
|
54
|
+
};
|
|
55
|
+
export declare function parseCustomAgent(input: unknown): CustomAgentParse;
|
|
56
|
+
/** Parses a list, reporting the first bad entry rather than silently dropping it. */
|
|
57
|
+
export declare function parseCustomAgents(input: unknown): {
|
|
58
|
+
ok: true;
|
|
59
|
+
agents: CustomAgent[];
|
|
60
|
+
} | {
|
|
61
|
+
ok: false;
|
|
62
|
+
error: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The detector rule for a custom name.
|
|
66
|
+
*
|
|
67
|
+
* Built with the same path-segment anchoring as the built-in rules, so
|
|
68
|
+
* `sagent` and `/usr/local/bin/sagent` match while `vim sagent` and
|
|
69
|
+
* `sagentry` do not. The name is escaped, so a declaration can never inject
|
|
70
|
+
* a pattern — `.*` is matched literally, not as a wildcard.
|
|
71
|
+
*/
|
|
72
|
+
export declare function customAgentRule(agent: CustomAgent): RegExp;
|
|
73
|
+
export interface TranscriptVars {
|
|
74
|
+
home: string;
|
|
75
|
+
cwd?: string;
|
|
76
|
+
tty?: string;
|
|
77
|
+
pid?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fill in a transcript template.
|
|
81
|
+
*
|
|
82
|
+
* Returns null when a placeholder the template uses has no value — an
|
|
83
|
+
* unresolved `{cwd}` would otherwise be looked up as a literal directory
|
|
84
|
+
* called "{cwd}", which silently never matches and looks like the user's
|
|
85
|
+
* declaration was wrong.
|
|
86
|
+
*/
|
|
87
|
+
export declare function expandTranscript(template: string, vars: TranscriptVars): string | null;
|
|
88
|
+
/**
|
|
89
|
+
* Split an expanded template into the directory to list and a matcher for the
|
|
90
|
+
* file name. A template with no `*` still goes through this, so one code path
|
|
91
|
+
* handles both.
|
|
92
|
+
*/
|
|
93
|
+
export declare function transcriptMatcher(expanded: string): {
|
|
94
|
+
dir: string;
|
|
95
|
+
match: (name: string) => boolean;
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=custom-agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-agents.d.ts","sourceRoot":"","sources":["../src/custom-agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAoD,CAAC;AAE3F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAWD,8FAA8F;AAC9F,eAAO,MAAM,eAAe,wCAAyC,CAAC;AAGtE,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAkDjE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAepH;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE1D;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAYtF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,CASrG"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TRANSCRIPT_VARS = exports.AI_KINDS = void 0;
|
|
4
|
+
exports.isAiKind = isAiKind;
|
|
5
|
+
exports.parseCustomAgent = parseCustomAgent;
|
|
6
|
+
exports.parseCustomAgents = parseCustomAgents;
|
|
7
|
+
exports.customAgentRule = customAgentRule;
|
|
8
|
+
exports.expandTranscript = expandTranscript;
|
|
9
|
+
exports.transcriptMatcher = transcriptMatcher;
|
|
10
|
+
exports.AI_KINDS = ['claude', 'codex', 'grok', 'augment'];
|
|
11
|
+
function isAiKind(value) {
|
|
12
|
+
return typeof value === 'string' && exports.AI_KINDS.includes(value);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A command name, not a pattern.
|
|
16
|
+
*
|
|
17
|
+
* No spaces and no path separators: the value is matched against one argv
|
|
18
|
+
* token, and anything looser invites an entry that matches every process on
|
|
19
|
+
* the machine. The characters allowed are the ones real binaries use.
|
|
20
|
+
*/
|
|
21
|
+
const NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,63}$/;
|
|
22
|
+
/** The placeholders expandTranscript understands. Anything else is a typo worth reporting. */
|
|
23
|
+
exports.TRANSCRIPT_VARS = ['home', 'cwd', 'tty', 'pid'];
|
|
24
|
+
const VAR_RE = /\{([a-z]+)\}/g;
|
|
25
|
+
function parseCustomAgent(input) {
|
|
26
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
27
|
+
return { ok: false, error: 'A custom agent must be an object' };
|
|
28
|
+
}
|
|
29
|
+
const raw = input;
|
|
30
|
+
const name = typeof raw.name === 'string' ? raw.name.trim() : '';
|
|
31
|
+
const kind = typeof raw.kind === 'string' ? raw.kind.trim().toLowerCase() : '';
|
|
32
|
+
const transcript = typeof raw.transcript === 'string' ? raw.transcript.trim() : '';
|
|
33
|
+
if (!NAME_RE.test(name)) {
|
|
34
|
+
return { ok: false, error: 'name must be a bare command name, e.g. sagent (letters, digits, . _ + -)' };
|
|
35
|
+
}
|
|
36
|
+
if (!isAiKind(kind)) {
|
|
37
|
+
return { ok: false, error: `kind must be one of ${exports.AI_KINDS.join(', ')}` };
|
|
38
|
+
}
|
|
39
|
+
if (!transcript) {
|
|
40
|
+
return { ok: false, error: 'transcript is required' };
|
|
41
|
+
}
|
|
42
|
+
// Anchored at {home} so a declaration cannot reach outside the user's own
|
|
43
|
+
// files even before the resolved path is re-checked.
|
|
44
|
+
if (!transcript.startsWith('{home}/')) {
|
|
45
|
+
return { ok: false, error: 'transcript must start with {home}/' };
|
|
46
|
+
}
|
|
47
|
+
if (transcript.includes('..')) {
|
|
48
|
+
return { ok: false, error: 'transcript must not contain ..' };
|
|
49
|
+
}
|
|
50
|
+
// A transcript is a file we parse, so the extension is part of the contract.
|
|
51
|
+
// Without this, `{home}/.ssh/*` is a legal declaration.
|
|
52
|
+
if (!/\.jsonl?$/.test(transcript)) {
|
|
53
|
+
return { ok: false, error: 'transcript must end in .json or .jsonl' };
|
|
54
|
+
}
|
|
55
|
+
// At most one glob, and only in the filename: a `*` in a directory segment
|
|
56
|
+
// would walk the home directory.
|
|
57
|
+
const slash = transcript.lastIndexOf('/');
|
|
58
|
+
if (transcript.slice(0, slash).includes('*')) {
|
|
59
|
+
return { ok: false, error: 'a * may only appear in the file name, not in a directory' };
|
|
60
|
+
}
|
|
61
|
+
if ((transcript.match(/\*/g) || []).length > 1) {
|
|
62
|
+
return { ok: false, error: 'transcript may contain at most one *' };
|
|
63
|
+
}
|
|
64
|
+
const unknown = [...transcript.matchAll(VAR_RE)]
|
|
65
|
+
.map((m) => m[1])
|
|
66
|
+
.filter((v) => !exports.TRANSCRIPT_VARS.includes(v));
|
|
67
|
+
if (unknown.length) {
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
error: `unknown placeholder {${unknown[0]}}; use ${exports.TRANSCRIPT_VARS.map((v) => `{${v}}`).join(', ')}`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { ok: true, agent: { name, kind, transcript } };
|
|
74
|
+
}
|
|
75
|
+
/** Parses a list, reporting the first bad entry rather than silently dropping it. */
|
|
76
|
+
function parseCustomAgents(input) {
|
|
77
|
+
if (input === undefined || input === null)
|
|
78
|
+
return { ok: true, agents: [] };
|
|
79
|
+
if (!Array.isArray(input))
|
|
80
|
+
return { ok: false, error: 'customAgents must be an array' };
|
|
81
|
+
const agents = [];
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
for (const entry of input) {
|
|
84
|
+
const parsed = parseCustomAgent(entry);
|
|
85
|
+
if (!parsed.ok)
|
|
86
|
+
return parsed;
|
|
87
|
+
if (seen.has(parsed.agent.name)) {
|
|
88
|
+
return { ok: false, error: `duplicate custom agent name: ${parsed.agent.name}` };
|
|
89
|
+
}
|
|
90
|
+
seen.add(parsed.agent.name);
|
|
91
|
+
agents.push(parsed.agent);
|
|
92
|
+
}
|
|
93
|
+
return { ok: true, agents };
|
|
94
|
+
}
|
|
95
|
+
function escapeRegExp(text) {
|
|
96
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The detector rule for a custom name.
|
|
100
|
+
*
|
|
101
|
+
* Built with the same path-segment anchoring as the built-in rules, so
|
|
102
|
+
* `sagent` and `/usr/local/bin/sagent` match while `vim sagent` and
|
|
103
|
+
* `sagentry` do not. The name is escaped, so a declaration can never inject
|
|
104
|
+
* a pattern — `.*` is matched literally, not as a wildcard.
|
|
105
|
+
*/
|
|
106
|
+
function customAgentRule(agent) {
|
|
107
|
+
return new RegExp(`(^|/)${escapeRegExp(agent.name)}(\\s|$)`);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Fill in a transcript template.
|
|
111
|
+
*
|
|
112
|
+
* Returns null when a placeholder the template uses has no value — an
|
|
113
|
+
* unresolved `{cwd}` would otherwise be looked up as a literal directory
|
|
114
|
+
* called "{cwd}", which silently never matches and looks like the user's
|
|
115
|
+
* declaration was wrong.
|
|
116
|
+
*/
|
|
117
|
+
function expandTranscript(template, vars) {
|
|
118
|
+
let missing = false;
|
|
119
|
+
const out = template.replace(VAR_RE, (_whole, name) => {
|
|
120
|
+
const value = name === 'home' ? vars.home
|
|
121
|
+
: name === 'cwd' ? vars.cwd
|
|
122
|
+
: name === 'tty' ? vars.tty
|
|
123
|
+
: name === 'pid' ? (vars.pid === undefined ? undefined : String(vars.pid))
|
|
124
|
+
: undefined;
|
|
125
|
+
if (!value) {
|
|
126
|
+
missing = true;
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
});
|
|
131
|
+
return missing ? null : out;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Split an expanded template into the directory to list and a matcher for the
|
|
135
|
+
* file name. A template with no `*` still goes through this, so one code path
|
|
136
|
+
* handles both.
|
|
137
|
+
*/
|
|
138
|
+
function transcriptMatcher(expanded) {
|
|
139
|
+
const slash = expanded.lastIndexOf('/');
|
|
140
|
+
const dir = expanded.slice(0, slash) || '/';
|
|
141
|
+
const base = expanded.slice(slash + 1);
|
|
142
|
+
if (!base.includes('*')) {
|
|
143
|
+
return { dir, match: (name) => name === base };
|
|
144
|
+
}
|
|
145
|
+
const re = new RegExp(`^${base.split('*').map(escapeRegExp).join('[^/]*')}$`);
|
|
146
|
+
return { dir, match: (name) => re.test(name) };
|
|
147
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-agents.test.d.ts","sourceRoot":"","sources":["../src/custom-agents.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const custom_agents_1 = require("./custom-agents");
|
|
5
|
+
const good = {
|
|
6
|
+
name: 'sagent',
|
|
7
|
+
kind: 'claude',
|
|
8
|
+
transcript: '{home}/.myagent/sessions/*.jsonl',
|
|
9
|
+
};
|
|
10
|
+
(0, vitest_1.describe)('parseCustomAgent', () => {
|
|
11
|
+
(0, vitest_1.it)('accepts a well-formed declaration', () => {
|
|
12
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)(good);
|
|
13
|
+
(0, vitest_1.expect)(parsed).toEqual({ ok: true, agent: good });
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)('trims and lowercases the kind, so "Claude" is not a mystery failure', () => {
|
|
16
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, kind: ' Claude ' });
|
|
17
|
+
(0, vitest_1.expect)(parsed.ok && parsed.agent.kind).toBe('claude');
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)('rejects a kind with no adapter behind it', () => {
|
|
20
|
+
// The whole point: `kind` chooses which parser runs. A kind we have no
|
|
21
|
+
// adapter for would produce a session with no conversation in it.
|
|
22
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, kind: 'augment-next' });
|
|
23
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.describe)('the path rules, which are the security boundary', () => {
|
|
26
|
+
// The agent runs as the user and streams whatever it is pointed at into a
|
|
27
|
+
// chat. These rules are what stop a declaration being a way to read
|
|
28
|
+
// arbitrary files.
|
|
29
|
+
(0, vitest_1.it)('requires the path to start at {home}', () => {
|
|
30
|
+
for (const transcript of ['/etc/passwd', '~/.ssh/id_rsa', '/{home}/x.jsonl', 'relative/x.jsonl']) {
|
|
31
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, transcript });
|
|
32
|
+
(0, vitest_1.expect)(parsed.ok, transcript).toBe(false);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
(0, vitest_1.it)('rejects traversal outright', () => {
|
|
36
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/../../etc/hosts.jsonl' });
|
|
37
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
(0, vitest_1.it)('requires a .json or .jsonl file, so {home}/.ssh/* is not declarable', () => {
|
|
40
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.ssh/*' });
|
|
41
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
42
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.x/a.json' }).ok).toBe(true);
|
|
43
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.x/a.jsonl' }).ok).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)('allows a glob only in the file name', () => {
|
|
46
|
+
// A '*' in a directory segment would walk the home directory.
|
|
47
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/*/sessions/a.jsonl' }).ok).toBe(false);
|
|
48
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.x/*.jsonl' }).ok).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
(0, vitest_1.it)('allows at most one glob', () => {
|
|
51
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.x/*-*.jsonl' }).ok).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
(0, vitest_1.it)('reports an unknown placeholder instead of looking up a literal directory', () => {
|
|
54
|
+
const parsed = (0, custom_agents_1.parseCustomAgent)({ ...good, transcript: '{home}/.x/{sessionid}/a.jsonl' });
|
|
55
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
56
|
+
(0, vitest_1.expect)(parsed.ok === false && parsed.error).toContain('{sessionid}');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
(0, vitest_1.describe)('the name rules', () => {
|
|
60
|
+
(0, vitest_1.it)('rejects a name that would match half the process table', () => {
|
|
61
|
+
for (const name of ['', ' ', '*', '.*', 'my agent', 'bin/agent', 'a'.repeat(65)]) {
|
|
62
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, name }).ok, JSON.stringify(name)).toBe(false);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
(0, vitest_1.it)('accepts the characters real binaries use', () => {
|
|
66
|
+
for (const name of ['agy', 'my-agent', 'my_agent', 'agent.sh', 'claude2', 'c++agent']) {
|
|
67
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)({ ...good, name }).ok, name).toBe(true);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
(0, vitest_1.it)('rejects junk rather than throwing', () => {
|
|
72
|
+
for (const bad of [null, undefined, 42, 'str', [], {}]) {
|
|
73
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgent)(bad).ok).toBe(false);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
(0, vitest_1.describe)('parseCustomAgents', () => {
|
|
78
|
+
(0, vitest_1.it)('treats absent as none', () => {
|
|
79
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgents)(undefined)).toEqual({ ok: true, agents: [] });
|
|
80
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgents)(null)).toEqual({ ok: true, agents: [] });
|
|
81
|
+
});
|
|
82
|
+
(0, vitest_1.it)('reports the first bad entry rather than silently dropping it', () => {
|
|
83
|
+
// Silently dropping would leave the user with a config they can see and a
|
|
84
|
+
// session they cannot, and nothing connecting the two.
|
|
85
|
+
const parsed = (0, custom_agents_1.parseCustomAgents)([good, { ...good, name: 'x', kind: 'nope' }]);
|
|
86
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
(0, vitest_1.it)('rejects two entries claiming one name', () => {
|
|
89
|
+
const parsed = (0, custom_agents_1.parseCustomAgents)([good, { ...good, transcript: '{home}/.other/a.json' }]);
|
|
90
|
+
(0, vitest_1.expect)(parsed.ok).toBe(false);
|
|
91
|
+
(0, vitest_1.expect)(parsed.ok === false && parsed.error).toContain('duplicate');
|
|
92
|
+
});
|
|
93
|
+
(0, vitest_1.it)('rejects a non-array', () => {
|
|
94
|
+
(0, vitest_1.expect)((0, custom_agents_1.parseCustomAgents)({ name: 'x' }).ok).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
(0, vitest_1.describe)('customAgentRule', () => {
|
|
98
|
+
const rule = (name) => (0, custom_agents_1.customAgentRule)({ ...good, name });
|
|
99
|
+
(0, vitest_1.it)('anchors on a path-segment boundary, like the built-in rules', () => {
|
|
100
|
+
(0, vitest_1.expect)(rule('sagent').test('sagent')).toBe(true);
|
|
101
|
+
(0, vitest_1.expect)(rule('sagent').test('sagent --resume')).toBe(true);
|
|
102
|
+
(0, vitest_1.expect)(rule('sagent').test('/usr/local/bin/sagent')).toBe(true);
|
|
103
|
+
// A bare space before the name is neither start-of-string nor a slash.
|
|
104
|
+
(0, vitest_1.expect)(rule('sagent').test('vim sagent')).toBe(false);
|
|
105
|
+
(0, vitest_1.expect)(rule('sagent').test('sagentry')).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.it)('escapes the name, so a declaration cannot inject a pattern', () => {
|
|
108
|
+
// '.' must match a literal dot and nothing else; without escaping,
|
|
109
|
+
// 'a.y' would match 'agy' — and a name of '.*' would match everything.
|
|
110
|
+
(0, vitest_1.expect)(rule('a.y').test('a.y')).toBe(true);
|
|
111
|
+
(0, vitest_1.expect)(rule('a.y').test('agy')).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
(0, vitest_1.describe)('expandTranscript', () => {
|
|
115
|
+
(0, vitest_1.it)('fills the placeholders it is given', () => {
|
|
116
|
+
(0, vitest_1.expect)((0, custom_agents_1.expandTranscript)('{home}/.x/{pid}/a.jsonl', { home: '/h', pid: 42 }))
|
|
117
|
+
.toBe('/h/.x/42/a.jsonl');
|
|
118
|
+
(0, vitest_1.expect)((0, custom_agents_1.expandTranscript)('{home}/.x/{tty}.json', { home: '/h', tty: '/dev/ttys1' }))
|
|
119
|
+
.toBe('/h/.x//dev/ttys1.json');
|
|
120
|
+
});
|
|
121
|
+
(0, vitest_1.it)('returns null when a placeholder it needs has no value', () => {
|
|
122
|
+
// Otherwise '{cwd}' is looked up as a literal directory of that name,
|
|
123
|
+
// which never matches and reads as "your declaration is wrong".
|
|
124
|
+
(0, vitest_1.expect)((0, custom_agents_1.expandTranscript)('{home}/.x/{cwd}/a.jsonl', { home: '/h' })).toBeNull();
|
|
125
|
+
(0, vitest_1.expect)((0, custom_agents_1.expandTranscript)('{home}/.x/a.jsonl', { home: '' })).toBeNull();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
(0, vitest_1.describe)('transcriptMatcher', () => {
|
|
129
|
+
(0, vitest_1.it)('matches an exact file name when there is no glob', () => {
|
|
130
|
+
const m = (0, custom_agents_1.transcriptMatcher)('/h/.x/chat.jsonl');
|
|
131
|
+
(0, vitest_1.expect)(m.dir).toBe('/h/.x');
|
|
132
|
+
(0, vitest_1.expect)(m.match('chat.jsonl')).toBe(true);
|
|
133
|
+
(0, vitest_1.expect)(m.match('other.jsonl')).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
(0, vitest_1.it)('expands a glob within the file name only', () => {
|
|
136
|
+
const m = (0, custom_agents_1.transcriptMatcher)('/h/.x/*.jsonl');
|
|
137
|
+
(0, vitest_1.expect)(m.dir).toBe('/h/.x');
|
|
138
|
+
(0, vitest_1.expect)(m.match('a.jsonl')).toBe(true);
|
|
139
|
+
(0, vitest_1.expect)(m.match('deep/a.jsonl')).toBe(false);
|
|
140
|
+
(0, vitest_1.expect)(m.match('a.json')).toBe(false);
|
|
141
|
+
});
|
|
142
|
+
(0, vitest_1.it)('treats the non-glob part of the name literally', () => {
|
|
143
|
+
const m = (0, custom_agents_1.transcriptMatcher)('/h/.x/roll.out-*.jsonl');
|
|
144
|
+
(0, vitest_1.expect)(m.match('roll.out-1.jsonl')).toBe(true);
|
|
145
|
+
(0, vitest_1.expect)(m.match('rollXout-1.jsonl')).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
(0, vitest_1.describe)('isAiKind', () => {
|
|
149
|
+
(0, vitest_1.it)('knows the four vendors with adapters', () => {
|
|
150
|
+
for (const k of ['claude', 'codex', 'grok', 'augment'])
|
|
151
|
+
(0, vitest_1.expect)((0, custom_agents_1.isAiKind)(k)).toBe(true);
|
|
152
|
+
for (const k of ['gemini', '', null, undefined, 7])
|
|
153
|
+
(0, vitest_1.expect)((0, custom_agents_1.isAiKind)(k)).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type { AiKind } from './kinds';
|
|
2
|
+
export type { CustomAgent, CustomAgentParse, TranscriptVars } from './custom-agents';
|
|
3
|
+
export { AI_KINDS, isAiKind, parseCustomAgent, parseCustomAgents, customAgentRule, expandTranscript, transcriptMatcher, TRANSCRIPT_VARS, } from './custom-agents';
|
|
2
4
|
export type { AiStatus, AiEvent, AiAdapter } from './events';
|
|
3
5
|
export { PREVIEW_LIMIT, preview } from './events';
|
|
4
6
|
export type { PermissionMode } from './permission';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.isSendable = exports.folderLabel = exports.shouldSendNotification = exports.isNotificationType = exports.parseTemplatePatch = exports.parseActions = exports.renderNotification = exports.categoryId = exports.MAX_ACTIONS = exports.BODY_MAX = exports.TITLE_MAX = exports.DEFAULT_TEMPLATES = exports.TEMPLATE_VARIABLES = exports.ACTION_KINDS = exports.NOTIFICATION_TYPES = exports.splitAttachments = exports.safeAttachmentName = exports.isImageName = exports.composeWithAttachments = exports.ATTACHMENT_MAX_FILES = exports.ATTACHMENT_MAX_BYTES = exports.ATTACHMENT_DIR = exports.promptMoveKeys = void 0;
|
|
3
|
+
exports.parseCapturePage = exports.MAX_CAPTURE_PAGE = exports.EMPTY_CAPTURE = exports.mergeEvents = exports.EMPTY_TRANSCRIPT = exports.resolveTmuxPrefs = exports.isValidTmuxColor = exports.isValidStatusTemplate = exports.compileStatusTemplate = exports.MAX_STATUS_TEMPLATE = exports.STATUS_TOKENS = exports.DEFAULT_TMUX_PREFS = exports.renderTerminalName = exports.factsFromSession = exports.TERMINAL_NAME_TOKENS = exports.DEFAULT_TERMINAL_TEMPLATE = exports.setFunctionKeysVisible = exports.getFunctionKeysVisible = exports.FUNCTION_KEYS_PREF = exports.shouldSubmitOnEnter = exports.COARSE_POINTER_QUERY = exports.rankCommands = exports.commandQuery = exports.toolAppearance = exports.toolClass = exports.shouldFollow = exports.PIN_THRESHOLD_PX = exports.readUserMessage = exports.dedent = exports.toolGroupStartsOpen = exports.groupEvents = exports.shouldAnnounceSession = exports.shouldNotifyNewAiSession = exports.shouldNotifyNewTerminal = exports.shouldNotifyPrompt = exports.shouldNotifyAi = exports.NOTIFY_COOLDOWN_MS = exports.REPLAY_LIMIT = exports.isPermissionMode = exports.PERMISSION_MODES = exports.preview = exports.PREVIEW_LIMIT = exports.TRANSCRIPT_VARS = exports.transcriptMatcher = exports.expandTranscript = exports.customAgentRule = exports.parseCustomAgents = exports.parseCustomAgent = exports.isAiKind = exports.AI_KINDS = void 0;
|
|
4
|
+
exports.isSendable = exports.folderLabel = exports.shouldSendNotification = exports.isNotificationType = exports.parseTemplatePatch = exports.parseActions = exports.renderNotification = exports.categoryId = exports.MAX_ACTIONS = exports.BODY_MAX = exports.TITLE_MAX = exports.DEFAULT_TEMPLATES = exports.TEMPLATE_VARIABLES = exports.ACTION_KINDS = exports.NOTIFICATION_TYPES = exports.splitAttachments = exports.safeAttachmentName = exports.isImageName = exports.composeWithAttachments = exports.ATTACHMENT_MAX_FILES = exports.ATTACHMENT_MAX_BYTES = exports.ATTACHMENT_DIR = exports.promptMoveKeys = exports.promptKeys = exports.isSafeKeyList = exports.isFreeTextOption = exports.freeTextRow = exports.detectPanePrompt = exports.PROMPT_KEYS = exports.thinkingLabel = exports.thinkingDuration = void 0;
|
|
5
|
+
var custom_agents_1 = require("./custom-agents");
|
|
6
|
+
Object.defineProperty(exports, "AI_KINDS", { enumerable: true, get: function () { return custom_agents_1.AI_KINDS; } });
|
|
7
|
+
Object.defineProperty(exports, "isAiKind", { enumerable: true, get: function () { return custom_agents_1.isAiKind; } });
|
|
8
|
+
Object.defineProperty(exports, "parseCustomAgent", { enumerable: true, get: function () { return custom_agents_1.parseCustomAgent; } });
|
|
9
|
+
Object.defineProperty(exports, "parseCustomAgents", { enumerable: true, get: function () { return custom_agents_1.parseCustomAgents; } });
|
|
10
|
+
Object.defineProperty(exports, "customAgentRule", { enumerable: true, get: function () { return custom_agents_1.customAgentRule; } });
|
|
11
|
+
Object.defineProperty(exports, "expandTranscript", { enumerable: true, get: function () { return custom_agents_1.expandTranscript; } });
|
|
12
|
+
Object.defineProperty(exports, "transcriptMatcher", { enumerable: true, get: function () { return custom_agents_1.transcriptMatcher; } });
|
|
13
|
+
Object.defineProperty(exports, "TRANSCRIPT_VARS", { enumerable: true, get: function () { return custom_agents_1.TRANSCRIPT_VARS; } });
|
|
5
14
|
var events_1 = require("./events");
|
|
6
15
|
Object.defineProperty(exports, "PREVIEW_LIMIT", { enumerable: true, get: function () { return events_1.PREVIEW_LIMIT; } });
|
|
7
16
|
Object.defineProperty(exports, "preview", { enumerable: true, get: function () { return events_1.preview; } });
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type AiKind = 'claude' | 'codex' | 'grok';
|
|
1
|
+
export type AiKind = 'claude' | 'codex' | 'grok' | 'augment';
|
|
2
2
|
//# sourceMappingURL=kinds.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../src/kinds.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../src/kinds.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":1,"sessions":{"e864cc5c-dad7-49c4-8666-6d7fb2297d2a":{"updatedAt":1793336945946,"files":{"/Volumes/SandeepSSD/www/github/dialout/packages/devdash-shared/src/index.ts":{"editCount":1,"findings":[]},"/Volumes/SandeepSSD/www/github/dialout/packages/devdash-agent/src/config.ts":{"editCount":2,"findings":[]},"/Volumes/SandeepSSD/www/github/dialout/packages/devdash-agent/src/ai-session-detector.ts":{"editCount":3,"findings":[]},"/Volumes/SandeepSSD/www/github/dialout/packages/devdash-agent/src/ai-transcript-locator.ts":{"editCount":4,"findings":[]}}}}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"entries": {
|
|
4
|
+
"79a93d4a2f8f50b95f852280616242fee1855dc99a3c75211917f55e72e95fae": {
|
|
5
|
+
"last_emitted_at_ms": 1793336950903,
|
|
6
|
+
"message": "Use parallel execution for independent tasks. Use run_in_background for long operations (npm install, builds, tests)."
|
|
7
|
+
},
|
|
8
|
+
"445ed27a3872b681d98190bae61ccb84954e1bc4e140df5370be958dee776b3a": {
|
|
9
|
+
"last_emitted_at_ms": 1793336884091,
|
|
10
|
+
"message": "Verify changes work after editing. Test functionality before marking complete."
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"updated_at": "2026-10-30T05:09:10.903Z"
|
|
14
|
+
}
|