@openscout/protocol 0.2.29 → 0.2.31
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/agent-identity.d.ts +4 -0
- package/dist/agent-identity.js +35 -10
- package/package.json +1 -1
- package/src/agent-identity.test.ts +9 -1
- package/src/agent-identity.ts +30 -12
package/dist/agent-identity.d.ts
CHANGED
|
@@ -39,6 +39,10 @@ export declare function constructAgentIdentity(input: AgentIdentityInput, option
|
|
|
39
39
|
raw?: string;
|
|
40
40
|
}): AgentIdentity | null;
|
|
41
41
|
export declare function extractAgentIdentities(text: string): AgentIdentity[];
|
|
42
|
+
export declare function extractAgentMentions(text: string): {
|
|
43
|
+
parsed: AgentIdentity[];
|
|
44
|
+
unparsed: string[];
|
|
45
|
+
};
|
|
42
46
|
export declare function agentIdentityMatches(identity: AgentIdentity, candidate: AgentIdentityCandidate): boolean;
|
|
43
47
|
export declare function resolveAgentIdentity<T extends AgentIdentityCandidate>(identity: AgentIdentity, candidates: T[]): T | null;
|
|
44
48
|
export declare function constructAgentAlias(input: {
|
package/dist/agent-identity.js
CHANGED
|
@@ -57,7 +57,8 @@ function parseSegmentedIdentity(raw) {
|
|
|
57
57
|
const next = {
|
|
58
58
|
definitionId: definitionPart,
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
// Collect positional (non-keyed) segments
|
|
61
|
+
const positional = [];
|
|
61
62
|
for (const part of parts) {
|
|
62
63
|
if (part.includes(":")) {
|
|
63
64
|
const [rawKey, rawValue = ""] = part.split(":", 2);
|
|
@@ -80,15 +81,29 @@ function parseSegmentedIdentity(raw) {
|
|
|
80
81
|
}
|
|
81
82
|
continue;
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
+
positional.push(part);
|
|
85
|
+
}
|
|
86
|
+
// 1 positional → workspaceQualifier (@agent.branch)
|
|
87
|
+
// 2 positionals → nodeQualifier.workspaceQualifier (@agent.node.branch — matches instance ID format)
|
|
88
|
+
// 3+ positionals → invalid
|
|
89
|
+
if (positional.length === 1) {
|
|
90
|
+
const value = normalizeAgentIdentitySegment(positional[0]);
|
|
91
|
+
if (!value)
|
|
84
92
|
return null;
|
|
85
|
-
}
|
|
86
|
-
const value = normalizeAgentIdentitySegment(part);
|
|
87
|
-
if (!value) {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
93
|
next.workspaceQualifier = value;
|
|
91
|
-
|
|
94
|
+
}
|
|
95
|
+
else if (positional.length === 2) {
|
|
96
|
+
const nodeValue = normalizeAgentIdentitySegment(positional[0]);
|
|
97
|
+
const workspaceValue = normalizeAgentIdentitySegment(positional[1]);
|
|
98
|
+
if (!nodeValue || !workspaceValue)
|
|
99
|
+
return null;
|
|
100
|
+
if (!next.nodeQualifier)
|
|
101
|
+
next.nodeQualifier = nodeValue;
|
|
102
|
+
if (!next.workspaceQualifier)
|
|
103
|
+
next.workspaceQualifier = workspaceValue;
|
|
104
|
+
}
|
|
105
|
+
else if (positional.length > 2) {
|
|
106
|
+
return null;
|
|
92
107
|
}
|
|
93
108
|
return constructAgentIdentity(next, { raw });
|
|
94
109
|
}
|
|
@@ -139,16 +154,26 @@ export function constructAgentIdentity(input, options = {}) {
|
|
|
139
154
|
};
|
|
140
155
|
}
|
|
141
156
|
export function extractAgentIdentities(text) {
|
|
157
|
+
return extractAgentMentions(text).parsed;
|
|
158
|
+
}
|
|
159
|
+
export function extractAgentMentions(text) {
|
|
142
160
|
const matches = Array.from(text.matchAll(/(^|\s)@([a-z0-9][a-z0-9._/:-]*)/gi));
|
|
143
161
|
const identities = new Map();
|
|
162
|
+
const unparsed = [];
|
|
144
163
|
for (const match of matches) {
|
|
145
|
-
const
|
|
164
|
+
const raw = match[2] ?? "";
|
|
165
|
+
const candidate = parseAgentIdentity(raw);
|
|
146
166
|
if (!candidate) {
|
|
167
|
+
if (raw)
|
|
168
|
+
unparsed.push(`@${raw}`);
|
|
147
169
|
continue;
|
|
148
170
|
}
|
|
149
171
|
identities.set(candidate.label, candidate);
|
|
150
172
|
}
|
|
151
|
-
return
|
|
173
|
+
return {
|
|
174
|
+
parsed: Array.from(identities.values()),
|
|
175
|
+
unparsed: Array.from(new Set(unparsed)),
|
|
176
|
+
};
|
|
152
177
|
}
|
|
153
178
|
function candidateAliases(candidate) {
|
|
154
179
|
const canonical = canonicalizeIdentity({
|
package/package.json
CHANGED
|
@@ -57,11 +57,19 @@ describe("agent identity grammar", () => {
|
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
test("parses 3-segment positional as definitionId.nodeQualifier.workspaceQualifier", () => {
|
|
61
|
+
const result = parseAgentIdentity("@arc.main.dev");
|
|
62
|
+
expect(result).not.toBeNull();
|
|
63
|
+
expect(result!.definitionId).toBe("arc");
|
|
64
|
+
expect(result!.nodeQualifier).toBe("main");
|
|
65
|
+
expect(result!.workspaceQualifier).toBe("dev");
|
|
66
|
+
});
|
|
67
|
+
|
|
60
68
|
test("rejects invalid and legacy-shaped identities", () => {
|
|
61
69
|
expect(parseAgentIdentity("")).toBeNull();
|
|
62
|
-
expect(parseAgentIdentity("@arc.main.dev")).toBeNull();
|
|
63
70
|
expect(parseAgentIdentity("@arc.profile:")).toBeNull();
|
|
64
71
|
expect(parseAgentIdentity("@arc@mini#main")).toBeNull();
|
|
72
|
+
expect(parseAgentIdentity("@arc.a.b.c")).toBeNull(); // 3+ positionals rejected
|
|
65
73
|
});
|
|
66
74
|
|
|
67
75
|
test("constructs canonical agent identities", () => {
|
package/src/agent-identity.ts
CHANGED
|
@@ -104,7 +104,8 @@ function parseSegmentedIdentity(raw: string): AgentIdentity | null {
|
|
|
104
104
|
definitionId: definitionPart,
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
// Collect positional (non-keyed) segments
|
|
108
|
+
const positional: string[] = [];
|
|
108
109
|
for (const part of parts) {
|
|
109
110
|
if (part.includes(":")) {
|
|
110
111
|
const [rawKey, rawValue = ""] = part.split(":", 2);
|
|
@@ -126,17 +127,24 @@ function parseSegmentedIdentity(raw: string): AgentIdentity | null {
|
|
|
126
127
|
continue;
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const value = normalizeAgentIdentitySegment(part);
|
|
134
|
-
if (!value) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
130
|
+
positional.push(part);
|
|
131
|
+
}
|
|
137
132
|
|
|
133
|
+
// 1 positional → workspaceQualifier (@agent.branch)
|
|
134
|
+
// 2 positionals → nodeQualifier.workspaceQualifier (@agent.node.branch — matches instance ID format)
|
|
135
|
+
// 3+ positionals → invalid
|
|
136
|
+
if (positional.length === 1) {
|
|
137
|
+
const value = normalizeAgentIdentitySegment(positional[0]);
|
|
138
|
+
if (!value) return null;
|
|
138
139
|
next.workspaceQualifier = value;
|
|
139
|
-
|
|
140
|
+
} else if (positional.length === 2) {
|
|
141
|
+
const nodeValue = normalizeAgentIdentitySegment(positional[0]);
|
|
142
|
+
const workspaceValue = normalizeAgentIdentitySegment(positional[1]);
|
|
143
|
+
if (!nodeValue || !workspaceValue) return null;
|
|
144
|
+
if (!next.nodeQualifier) next.nodeQualifier = nodeValue;
|
|
145
|
+
if (!next.workspaceQualifier) next.workspaceQualifier = workspaceValue;
|
|
146
|
+
} else if (positional.length > 2) {
|
|
147
|
+
return null;
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
return constructAgentIdentity(next, { raw });
|
|
@@ -204,21 +212,31 @@ export function constructAgentIdentity(
|
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
export function extractAgentIdentities(text: string): AgentIdentity[] {
|
|
215
|
+
return extractAgentMentions(text).parsed;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function extractAgentMentions(text: string): { parsed: AgentIdentity[]; unparsed: string[] } {
|
|
207
219
|
const matches = Array.from(
|
|
208
220
|
text.matchAll(/(^|\s)@([a-z0-9][a-z0-9._/:-]*)/gi),
|
|
209
221
|
);
|
|
210
222
|
const identities = new Map<string, AgentIdentity>();
|
|
223
|
+
const unparsed: string[] = [];
|
|
211
224
|
|
|
212
225
|
for (const match of matches) {
|
|
213
|
-
const
|
|
226
|
+
const raw = match[2] ?? "";
|
|
227
|
+
const candidate = parseAgentIdentity(raw);
|
|
214
228
|
if (!candidate) {
|
|
229
|
+
if (raw) unparsed.push(`@${raw}`);
|
|
215
230
|
continue;
|
|
216
231
|
}
|
|
217
232
|
|
|
218
233
|
identities.set(candidate.label, candidate);
|
|
219
234
|
}
|
|
220
235
|
|
|
221
|
-
return
|
|
236
|
+
return {
|
|
237
|
+
parsed: Array.from(identities.values()),
|
|
238
|
+
unparsed: Array.from(new Set(unparsed)),
|
|
239
|
+
};
|
|
222
240
|
}
|
|
223
241
|
|
|
224
242
|
function candidateAliases(candidate: AgentIdentityCandidate): string[] {
|