@tanstack/intent 0.0.6 → 0.0.7
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 +11 -12
- package/dist/cli.mjs +155 -129
- package/dist/display-D_XzuGnu.mjs +54 -0
- package/dist/index.d.mts +3 -17
- package/dist/index.mjs +245 -4
- package/dist/intent-library.mjs +3 -52
- package/dist/library-scanner.d.mts +1 -1
- package/dist/library-scanner.mjs +1 -1
- package/dist/{setup-BvrZZLsA.mjs → setup-DGvdyKEq.mjs} +29 -11
- package/dist/setup.d.mts +1 -1
- package/dist/setup.mjs +1 -1
- package/meta/domain-discovery/SKILL.md +40 -5
- package/meta/feedback-collection/SKILL.md +73 -62
- package/meta/tree-generator/SKILL.md +9 -1
- package/package.json +1 -1
- package/dist/feedback-BTSaBAS_.mjs +0 -299
- package/dist/feedback-PR8JNBfM.mjs +0 -3
- package/dist/init-BU1ZnUbK.mjs +0 -3
- package/dist/init-DUiDMMrN.mjs +0 -72
- /package/dist/{library-scanner-D0aP7is_.mjs → library-scanner-V9sTOhrb.mjs} +0 -0
- /package/dist/{setup-D2Bwubpw.d.mts → setup-BJ4giTKA.d.mts} +0 -0
- /package/dist/{types-B20LP96b.d.mts → types-BmnI8kFB.d.mts} +0 -0
|
@@ -520,10 +520,18 @@ See also: [lib]-core/[other-domain]/SKILL.md § Common Mistakes
|
|
|
520
520
|
The cross-reference ensures agents that load one skill are pointed
|
|
521
521
|
toward the related skill where the other side of the tension lives.
|
|
522
522
|
|
|
523
|
+
Also check the domain map's `cross_references` section for non-tension
|
|
524
|
+
relationships between skills. For each cross-reference, add a "See also"
|
|
525
|
+
line at the end of the relevant skill's body:
|
|
526
|
+
|
|
527
|
+
```markdown
|
|
528
|
+
See also: [other-skill]/SKILL.md — [reason]
|
|
529
|
+
```
|
|
530
|
+
|
|
523
531
|
### Step 6 — Write composition skills (if applicable)
|
|
524
532
|
|
|
525
533
|
Use the `compositions` entries from `domain_map.yaml` (populated during
|
|
526
|
-
skill-domain-discovery Phase
|
|
534
|
+
skill-domain-discovery Phase 3h) to identify which composition skills
|
|
527
535
|
to produce.
|
|
528
536
|
|
|
529
537
|
Composition skills cover how two or more libraries work together. These
|
package/package.json
CHANGED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { execSync } from "node:child_process";
|
|
4
|
-
|
|
5
|
-
//#region src/feedback.ts
|
|
6
|
-
const META_FEEDBACK_REPO = "TanStack/intent";
|
|
7
|
-
const SECRET_PATTERNS = [
|
|
8
|
-
/(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/,
|
|
9
|
-
/(?:sk|pk)[-_](?:live|test)[-_][A-Za-z0-9]{24,}/,
|
|
10
|
-
/AKIA[0-9A-Z]{16}/,
|
|
11
|
-
/-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/,
|
|
12
|
-
/eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/,
|
|
13
|
-
/(?:Bearer|token)\s+[A-Za-z0-9_\-.~+/]{20,}/i,
|
|
14
|
-
/[A-Za-z0-9]{32,}(?=.*(?:key|secret|token|password))/i
|
|
15
|
-
];
|
|
16
|
-
function containsSecrets(text) {
|
|
17
|
-
return SECRET_PATTERNS.some((pattern) => pattern.test(text));
|
|
18
|
-
}
|
|
19
|
-
function hasGhCli() {
|
|
20
|
-
try {
|
|
21
|
-
execSync("gh --version", { stdio: "ignore" });
|
|
22
|
-
return true;
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function getHomeConfigDir() {
|
|
28
|
-
return process.env.XDG_CONFIG_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".config");
|
|
29
|
-
}
|
|
30
|
-
function resolveFrequency(root) {
|
|
31
|
-
const userConfigPath = join(getHomeConfigDir(), "intent", "config.json");
|
|
32
|
-
try {
|
|
33
|
-
const userCfg = JSON.parse(readFileSync(userConfigPath, "utf8"));
|
|
34
|
-
if (userCfg.feedback?.frequency) return userCfg.feedback.frequency;
|
|
35
|
-
} catch {}
|
|
36
|
-
const projectConfigPath = join(root, "intent.config.json");
|
|
37
|
-
try {
|
|
38
|
-
const projCfg = JSON.parse(readFileSync(projectConfigPath, "utf8"));
|
|
39
|
-
if (projCfg.feedback?.frequency) return projCfg.feedback.frequency;
|
|
40
|
-
} catch {}
|
|
41
|
-
return "every-5";
|
|
42
|
-
}
|
|
43
|
-
const REQUIRED_FIELDS = [
|
|
44
|
-
"skill",
|
|
45
|
-
"package",
|
|
46
|
-
"skillVersion",
|
|
47
|
-
"task",
|
|
48
|
-
"whatWorked",
|
|
49
|
-
"whatFailed",
|
|
50
|
-
"missing",
|
|
51
|
-
"selfCorrections",
|
|
52
|
-
"userRating"
|
|
53
|
-
];
|
|
54
|
-
function validatePayload(payload) {
|
|
55
|
-
const errors = [];
|
|
56
|
-
if (!payload || typeof payload !== "object") return {
|
|
57
|
-
valid: false,
|
|
58
|
-
errors: ["Payload must be a JSON object"]
|
|
59
|
-
};
|
|
60
|
-
const obj = payload;
|
|
61
|
-
for (const field of REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
|
|
62
|
-
if (obj.userRating && ![
|
|
63
|
-
"good",
|
|
64
|
-
"mixed",
|
|
65
|
-
"bad"
|
|
66
|
-
].includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
|
|
67
|
-
if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
|
|
68
|
-
return {
|
|
69
|
-
valid: errors.length === 0,
|
|
70
|
-
errors
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
const META_REQUIRED_FIELDS = [
|
|
74
|
-
"metaSkill",
|
|
75
|
-
"library",
|
|
76
|
-
"agentUsed",
|
|
77
|
-
"artifactQuality",
|
|
78
|
-
"whatWorked",
|
|
79
|
-
"whatFailed",
|
|
80
|
-
"suggestions",
|
|
81
|
-
"userRating"
|
|
82
|
-
];
|
|
83
|
-
const VALID_META_SKILLS = [
|
|
84
|
-
"domain-discovery",
|
|
85
|
-
"tree-generator",
|
|
86
|
-
"generate-skill",
|
|
87
|
-
"skill-staleness-check"
|
|
88
|
-
];
|
|
89
|
-
const VALID_AGENTS = [
|
|
90
|
-
"claude-code",
|
|
91
|
-
"cursor",
|
|
92
|
-
"copilot",
|
|
93
|
-
"codex",
|
|
94
|
-
"other"
|
|
95
|
-
];
|
|
96
|
-
const VALID_QUALITY_RATINGS = [
|
|
97
|
-
"good",
|
|
98
|
-
"mixed",
|
|
99
|
-
"bad"
|
|
100
|
-
];
|
|
101
|
-
function validateMetaPayload(payload) {
|
|
102
|
-
const errors = [];
|
|
103
|
-
if (!payload || typeof payload !== "object") return {
|
|
104
|
-
valid: false,
|
|
105
|
-
errors: ["Payload must be a JSON object"]
|
|
106
|
-
};
|
|
107
|
-
const obj = payload;
|
|
108
|
-
for (const field of META_REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
|
|
109
|
-
if (obj.metaSkill && !VALID_META_SKILLS.includes(obj.metaSkill)) errors.push(`metaSkill must be one of: ${VALID_META_SKILLS.join(", ")}`);
|
|
110
|
-
if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed)) errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(", ")}`);
|
|
111
|
-
if (obj.artifactQuality && !VALID_QUALITY_RATINGS.includes(obj.artifactQuality)) errors.push("artifactQuality must be one of: good, mixed, bad");
|
|
112
|
-
if (obj.userRating && !VALID_QUALITY_RATINGS.includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
|
|
113
|
-
if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
|
|
114
|
-
return {
|
|
115
|
-
valid: errors.length === 0,
|
|
116
|
-
errors
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
function metaToMarkdown(payload) {
|
|
120
|
-
const lines = [
|
|
121
|
-
`# Meta-Skill Feedback: ${payload.metaSkill}`,
|
|
122
|
-
"",
|
|
123
|
-
`**Library:** ${payload.library}`,
|
|
124
|
-
`**Agent:** ${payload.agentUsed}`,
|
|
125
|
-
`**Artifact quality:** ${payload.artifactQuality}`,
|
|
126
|
-
`**Rating:** ${payload.userRating}`
|
|
127
|
-
];
|
|
128
|
-
if (payload.interviewQuality) lines.push(`**Interview quality:** ${payload.interviewQuality}`);
|
|
129
|
-
if (payload.failureModeQuality) lines.push(`**Failure mode quality:** ${payload.failureModeQuality}`);
|
|
130
|
-
lines.push("", "## What Worked", payload.whatWorked, "", "## What Failed", payload.whatFailed, "", "## Suggestions", payload.suggestions);
|
|
131
|
-
return lines.join("\n") + "\n";
|
|
132
|
-
}
|
|
133
|
-
function toMarkdown(payload) {
|
|
134
|
-
const lines = [
|
|
135
|
-
`# Skill Feedback: ${payload.skill}`,
|
|
136
|
-
"",
|
|
137
|
-
`**Package:** ${payload.package}`,
|
|
138
|
-
`**Skill version:** ${payload.skillVersion}`,
|
|
139
|
-
`**Rating:** ${payload.userRating}`,
|
|
140
|
-
"",
|
|
141
|
-
"## Task",
|
|
142
|
-
payload.task,
|
|
143
|
-
"",
|
|
144
|
-
"## What Worked",
|
|
145
|
-
payload.whatWorked,
|
|
146
|
-
"",
|
|
147
|
-
"## What Failed",
|
|
148
|
-
payload.whatFailed,
|
|
149
|
-
"",
|
|
150
|
-
"## Missing",
|
|
151
|
-
payload.missing,
|
|
152
|
-
"",
|
|
153
|
-
"## Self-Corrections",
|
|
154
|
-
payload.selfCorrections
|
|
155
|
-
];
|
|
156
|
-
if (payload.userComments) lines.push("", "## User Comments", payload.userComments);
|
|
157
|
-
return lines.join("\n") + "\n";
|
|
158
|
-
}
|
|
159
|
-
function submitFeedback(payload, repo, opts) {
|
|
160
|
-
const md = toMarkdown(payload);
|
|
161
|
-
if (opts.ghAvailable) try {
|
|
162
|
-
execSync(`gh issue create --repo ${repo} --title "${`Skill Feedback: ${payload.skill} (${payload.userRating})`.replace(/"/g, "\\\"")}" --body -`, {
|
|
163
|
-
input: md,
|
|
164
|
-
stdio: [
|
|
165
|
-
"pipe",
|
|
166
|
-
"pipe",
|
|
167
|
-
"pipe"
|
|
168
|
-
]
|
|
169
|
-
});
|
|
170
|
-
return {
|
|
171
|
-
method: "gh",
|
|
172
|
-
detail: `Submitted issue to ${repo}`
|
|
173
|
-
};
|
|
174
|
-
} catch {}
|
|
175
|
-
if (opts.outputPath) {
|
|
176
|
-
writeFileSync(opts.outputPath, md, "utf8");
|
|
177
|
-
return {
|
|
178
|
-
method: "file",
|
|
179
|
-
detail: `Saved to ${opts.outputPath}`
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
return {
|
|
183
|
-
method: "stdout",
|
|
184
|
-
detail: md
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
function submitMetaFeedback(payload, opts) {
|
|
188
|
-
const md = metaToMarkdown(payload);
|
|
189
|
-
if (opts.ghAvailable) try {
|
|
190
|
-
execSync(`gh issue create --repo ${META_FEEDBACK_REPO} --title "${`Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})`.replace(/"/g, "\\\"")}" --label "feedback:${payload.metaSkill}" --body -`, {
|
|
191
|
-
input: md,
|
|
192
|
-
stdio: [
|
|
193
|
-
"pipe",
|
|
194
|
-
"pipe",
|
|
195
|
-
"pipe"
|
|
196
|
-
]
|
|
197
|
-
});
|
|
198
|
-
return {
|
|
199
|
-
method: "gh",
|
|
200
|
-
detail: `Submitted issue to ${META_FEEDBACK_REPO}`
|
|
201
|
-
};
|
|
202
|
-
} catch {}
|
|
203
|
-
if (opts.outputPath) {
|
|
204
|
-
writeFileSync(opts.outputPath, md, "utf8");
|
|
205
|
-
return {
|
|
206
|
-
method: "file",
|
|
207
|
-
detail: `Saved to ${opts.outputPath}`
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
method: "stdout",
|
|
212
|
-
detail: md
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
function runFeedback(args) {
|
|
216
|
-
const isMeta = args.includes("--meta");
|
|
217
|
-
const submitFlag = args.includes("--submit");
|
|
218
|
-
const fileIdx = args.indexOf("--file");
|
|
219
|
-
const filePath = fileIdx !== -1 ? args[fileIdx + 1] : void 0;
|
|
220
|
-
if (!submitFlag || !filePath) {
|
|
221
|
-
if (isMeta) console.error("Usage: intent feedback --meta --submit --file <path>");
|
|
222
|
-
else console.error("Usage: intent feedback --submit --file <path>");
|
|
223
|
-
process.exit(1);
|
|
224
|
-
}
|
|
225
|
-
if (!existsSync(filePath)) {
|
|
226
|
-
console.error(`File not found: ${filePath}`);
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
let raw;
|
|
230
|
-
try {
|
|
231
|
-
raw = JSON.parse(readFileSync(filePath, "utf8"));
|
|
232
|
-
} catch {
|
|
233
|
-
console.error("Invalid JSON in feedback file");
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
const ghAvailable = hasGhCli();
|
|
237
|
-
if (resolveFrequency(process.cwd()) === "never") {
|
|
238
|
-
console.log("Feedback is disabled (frequency: never)");
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const dateSuffix = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
242
|
-
if (isMeta) {
|
|
243
|
-
const validation$1 = validateMetaPayload(raw);
|
|
244
|
-
if (!validation$1.valid) {
|
|
245
|
-
console.error("Meta-feedback validation failed:");
|
|
246
|
-
for (const err of validation$1.errors) console.error(` - ${err}`);
|
|
247
|
-
process.exit(1);
|
|
248
|
-
}
|
|
249
|
-
const payload$1 = raw;
|
|
250
|
-
const fallbackPath$1 = `intent-meta-feedback-${dateSuffix}.md`;
|
|
251
|
-
const result$1 = submitMetaFeedback(payload$1, {
|
|
252
|
-
ghAvailable,
|
|
253
|
-
outputPath: ghAvailable ? void 0 : fallbackPath$1
|
|
254
|
-
});
|
|
255
|
-
switch (result$1.method) {
|
|
256
|
-
case "gh":
|
|
257
|
-
console.log(`✓ ${result$1.detail}`);
|
|
258
|
-
break;
|
|
259
|
-
case "file":
|
|
260
|
-
console.log(`✓ ${result$1.detail}`);
|
|
261
|
-
console.log(`You can manually open an issue at https://github.com/${META_FEEDBACK_REPO}/issues with this content.`);
|
|
262
|
-
break;
|
|
263
|
-
case "stdout":
|
|
264
|
-
console.log("--- Meta-feedback markdown (copy/paste to issue) ---");
|
|
265
|
-
console.log(result$1.detail);
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
const validation = validatePayload(raw);
|
|
271
|
-
if (!validation.valid) {
|
|
272
|
-
console.error("Feedback validation failed:");
|
|
273
|
-
for (const err of validation.errors) console.error(` - ${err}`);
|
|
274
|
-
process.exit(1);
|
|
275
|
-
}
|
|
276
|
-
const payload = raw;
|
|
277
|
-
const repo = payload.package.replace(/^@/, "").replace(/\//, "/");
|
|
278
|
-
const fallbackPath = `intent-feedback-${dateSuffix}.md`;
|
|
279
|
-
const result = submitFeedback(payload, repo, {
|
|
280
|
-
ghAvailable,
|
|
281
|
-
outputPath: ghAvailable ? void 0 : fallbackPath
|
|
282
|
-
});
|
|
283
|
-
switch (result.method) {
|
|
284
|
-
case "gh":
|
|
285
|
-
console.log(`✓ ${result.detail}`);
|
|
286
|
-
break;
|
|
287
|
-
case "file":
|
|
288
|
-
console.log(`✓ ${result.detail}`);
|
|
289
|
-
console.log("You can manually open an issue with this content.");
|
|
290
|
-
break;
|
|
291
|
-
case "stdout":
|
|
292
|
-
console.log("--- Feedback markdown (copy/paste to issue) ---");
|
|
293
|
-
console.log(result.detail);
|
|
294
|
-
break;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
//#endregion
|
|
299
|
-
export { runFeedback as a, toMarkdown as c, resolveFrequency as i, validateMetaPayload as l, hasGhCli as n, submitFeedback as o, metaToMarkdown as r, submitMetaFeedback as s, containsSecrets as t, validatePayload as u };
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { a as runFeedback, c as toMarkdown, i as resolveFrequency, l as validateMetaPayload, n as hasGhCli, o as submitFeedback, r as metaToMarkdown, s as submitMetaFeedback, t as containsSecrets, u as validatePayload } from "./feedback-BTSaBAS_.mjs";
|
|
2
|
-
|
|
3
|
-
export { runFeedback };
|
package/dist/init-BU1ZnUbK.mjs
DELETED
package/dist/init-DUiDMMrN.mjs
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
|
|
4
|
-
//#region src/init.ts
|
|
5
|
-
const AGENT_CONFIG_FILES = [
|
|
6
|
-
"AGENTS.md",
|
|
7
|
-
"CLAUDE.md",
|
|
8
|
-
".cursorrules",
|
|
9
|
-
".github/copilot-instructions.md"
|
|
10
|
-
];
|
|
11
|
-
const INTENT_BLOCK_MARKER = "## Intent Skills";
|
|
12
|
-
const INTENT_BLOCK = `## Intent Skills
|
|
13
|
-
|
|
14
|
-
This project uses TanStack Intent. Run \`npx intent list\` to discover
|
|
15
|
-
available AI coding skills. Before working with a library that has skills,
|
|
16
|
-
read the relevant SKILL.md file at the path shown in the list output.
|
|
17
|
-
After completing a task that used skills, collect and submit feedback
|
|
18
|
-
following the instructions in the list output.
|
|
19
|
-
`;
|
|
20
|
-
const DEFAULT_CONFIG = { feedback: { frequency: "every-5" } };
|
|
21
|
-
function detectAgentConfigs(root) {
|
|
22
|
-
return AGENT_CONFIG_FILES.map((f) => join(root, f)).filter((f) => existsSync(f));
|
|
23
|
-
}
|
|
24
|
-
function hasIntentBlock(filePath) {
|
|
25
|
-
try {
|
|
26
|
-
return readFileSync(filePath, "utf8").includes(INTENT_BLOCK_MARKER);
|
|
27
|
-
} catch {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function injectIntentBlock(filePath) {
|
|
32
|
-
if (hasIntentBlock(filePath)) return false;
|
|
33
|
-
let content;
|
|
34
|
-
try {
|
|
35
|
-
content = readFileSync(filePath, "utf8");
|
|
36
|
-
} catch {
|
|
37
|
-
content = "";
|
|
38
|
-
}
|
|
39
|
-
const separator = content.length > 0 && !content.endsWith("\n\n") ? "\n\n" : "";
|
|
40
|
-
writeFileSync(filePath, content + separator + INTENT_BLOCK);
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
function writeProjectConfig(root) {
|
|
44
|
-
const configPath = join(root, "intent.config.json");
|
|
45
|
-
if (!existsSync(configPath)) writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
|
|
46
|
-
return configPath;
|
|
47
|
-
}
|
|
48
|
-
function readProjectConfig(root) {
|
|
49
|
-
const configPath = join(root, "intent.config.json");
|
|
50
|
-
try {
|
|
51
|
-
return JSON.parse(readFileSync(configPath, "utf8"));
|
|
52
|
-
} catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function runInit(root) {
|
|
57
|
-
const detected = detectAgentConfigs(root);
|
|
58
|
-
const injected = [];
|
|
59
|
-
const skipped = [];
|
|
60
|
-
const created = [];
|
|
61
|
-
for (const filePath of detected) if (injectIntentBlock(filePath)) injected.push(filePath);
|
|
62
|
-
else skipped.push(filePath);
|
|
63
|
-
return {
|
|
64
|
-
injected,
|
|
65
|
-
skipped,
|
|
66
|
-
created,
|
|
67
|
-
configPath: writeProjectConfig(root)
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
//#endregion
|
|
72
|
-
export { runInit as a, readProjectConfig as i, hasIntentBlock as n, writeProjectConfig as o, injectIntentBlock as r, detectAgentConfigs as t };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|