prjct-cli 1.8.0 → 1.10.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/core/__tests__/agentic/domain-classifier.test.ts +330 -0
  3. package/core/__tests__/agentic/prompt-assembly.test.ts +298 -0
  4. package/core/__tests__/agentic/prompt-builder.test.ts +2 -2
  5. package/core/__tests__/agentic/response-validator.test.ts +263 -0
  6. package/core/__tests__/agentic/smart-context.test.ts +3 -3
  7. package/core/__tests__/agentic/token-budget.test.ts +294 -0
  8. package/core/__tests__/schemas/model.test.ts +272 -0
  9. package/core/agentic/anti-hallucination.ts +124 -0
  10. package/core/agentic/domain-classifier.ts +525 -0
  11. package/core/agentic/environment-block.ts +102 -0
  12. package/core/agentic/index.ts +1 -0
  13. package/core/agentic/injection-validator.ts +16 -0
  14. package/core/agentic/orchestrator-executor.ts +43 -199
  15. package/core/agentic/prompt-builder.ts +352 -158
  16. package/core/agentic/response-validator.ts +98 -0
  17. package/core/agentic/smart-context.ts +60 -144
  18. package/core/agentic/token-budget.ts +226 -0
  19. package/core/infrastructure/ai-provider.ts +35 -0
  20. package/core/schemas/analysis.ts +4 -0
  21. package/core/schemas/classification.ts +91 -0
  22. package/core/schemas/index.ts +6 -0
  23. package/core/schemas/llm-output.ts +170 -0
  24. package/core/schemas/model.ts +153 -0
  25. package/core/schemas/state.ts +3 -0
  26. package/core/services/context-selector.ts +8 -2
  27. package/core/types/config.ts +2 -0
  28. package/core/types/provider.ts +12 -0
  29. package/dist/bin/prjct.mjs +2146 -1347
  30. package/dist/core/infrastructure/command-installer.js +78 -7
  31. package/dist/core/infrastructure/setup.js +78 -7
  32. package/package.json +1 -1
@@ -31,6 +31,46 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
+ // core/schemas/model.ts
35
+ function compareSemver(a, b) {
36
+ const pa = a.split(".").map(Number);
37
+ const pb = b.split(".").map(Number);
38
+ for (let i = 0; i < 3; i++) {
39
+ const va = pa[i] ?? 0;
40
+ const vb = pb[i] ?? 0;
41
+ if (va < vb) return -1;
42
+ if (va > vb) return 1;
43
+ }
44
+ return 0;
45
+ }
46
+ var import_zod, ClaudeModelSchema, GeminiModelSchema, AIModelSchema, ModelMetadataSchema, ModelPreferenceSchema;
47
+ var init_model = __esm({
48
+ "core/schemas/model.ts"() {
49
+ "use strict";
50
+ import_zod = require("zod");
51
+ ClaudeModelSchema = import_zod.z.enum(["opus", "sonnet", "haiku"]);
52
+ GeminiModelSchema = import_zod.z.enum(["2.5-pro", "2.5-flash", "2.0-flash"]);
53
+ AIModelSchema = import_zod.z.string().min(1);
54
+ ModelMetadataSchema = import_zod.z.object({
55
+ /** Provider name (e.g., 'claude', 'gemini') */
56
+ provider: import_zod.z.string(),
57
+ /** Model identifier (e.g., 'opus', 'sonnet', '2.5-pro') */
58
+ model: import_zod.z.string(),
59
+ /** CLI version used */
60
+ cliVersion: import_zod.z.string().optional(),
61
+ /** When this was recorded */
62
+ recordedAt: import_zod.z.string()
63
+ });
64
+ ModelPreferenceSchema = import_zod.z.object({
65
+ /** Preferred model for this project */
66
+ preferredModel: import_zod.z.string().optional(),
67
+ /** Model used for last analysis (for mismatch detection) */
68
+ lastAnalysisModel: ModelMetadataSchema.optional()
69
+ });
70
+ __name(compareSemver, "compareSemver");
71
+ }
72
+ });
73
+
34
74
  // core/utils/fs-helpers.ts
35
75
  async function fileExists(filePath) {
36
76
  try {
@@ -109,7 +149,8 @@ __export(ai_provider_exports, {
109
149
  hasProviderConfig: () => hasProviderConfig,
110
150
  needsCursorRouterRegeneration: () => needsCursorRouterRegeneration,
111
151
  needsWindsurfRouterRegeneration: () => needsWindsurfRouterRegeneration,
112
- selectProvider: () => selectProvider
152
+ selectProvider: () => selectProvider,
153
+ validateCliVersion: () => validateCliVersion
113
154
  });
114
155
  async function whichCommand(command) {
115
156
  try {
@@ -138,12 +179,22 @@ async function detectProvider(provider) {
138
179
  return { installed: false };
139
180
  }
140
181
  const version = await getCliVersion(config.cliCommand);
182
+ const versionWarning = validateCliVersion(provider, version || void 0);
141
183
  return {
142
184
  installed: true,
143
185
  version: version || void 0,
144
- path: cliPath
186
+ path: cliPath,
187
+ versionWarning: versionWarning || void 0
145
188
  };
146
189
  }
190
+ function validateCliVersion(provider, version) {
191
+ const config = Providers[provider];
192
+ if (!config.minCliVersion || !version) return null;
193
+ if (compareSemver(version, config.minCliVersion) < 0) {
194
+ return `\u26A0\uFE0F ${config.displayName} v${version} is below minimum v${config.minCliVersion}. Some features may not work correctly.`;
195
+ }
196
+ return null;
197
+ }
147
198
  async function detectAllProviders(refresh = false) {
148
199
  if (!refresh) {
149
200
  const cached = await readProviderCache();
@@ -305,6 +356,7 @@ var init_ai_provider = __esm({
305
356
  import_node_os2 = __toESM(require("node:os"));
306
357
  import_node_path3 = __toESM(require("node:path"));
307
358
  import_node_util = require("node:util");
359
+ init_model();
308
360
  init_fs_helpers();
309
361
  init_provider_cache();
310
362
  execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
@@ -322,7 +374,10 @@ var init_ai_provider = __esm({
322
374
  projectSettingsFile: "settings.local.json",
323
375
  ignoreFile: ".claudeignore",
324
376
  websiteUrl: "https://www.anthropic.com/claude",
325
- docsUrl: "https://docs.anthropic.com/claude-code"
377
+ docsUrl: "https://docs.anthropic.com/claude-code",
378
+ defaultModel: "sonnet",
379
+ supportedModels: ["opus", "sonnet", "haiku"],
380
+ minCliVersion: "1.0.0"
326
381
  };
327
382
  GeminiProvider = {
328
383
  name: "gemini",
@@ -337,7 +392,10 @@ var init_ai_provider = __esm({
337
392
  projectSettingsFile: "settings.json",
338
393
  ignoreFile: ".geminiignore",
339
394
  websiteUrl: "https://geminicli.com",
340
- docsUrl: "https://geminicli.com/docs"
395
+ docsUrl: "https://geminicli.com/docs",
396
+ defaultModel: "2.5-flash",
397
+ supportedModels: ["2.5-pro", "2.5-flash", "2.0-flash"],
398
+ minCliVersion: "1.0.0"
341
399
  };
342
400
  AntigravityProvider = {
343
401
  name: "antigravity",
@@ -357,7 +415,11 @@ var init_ai_provider = __esm({
357
415
  ignoreFile: ".agentignore",
358
416
  // Assumed
359
417
  websiteUrl: "https://gemini.google.com/app/antigravity",
360
- docsUrl: "https://gemini.google.com/app/antigravity"
418
+ docsUrl: "https://gemini.google.com/app/antigravity",
419
+ defaultModel: null,
420
+ // Platform-managed
421
+ supportedModels: [],
422
+ minCliVersion: null
361
423
  };
362
424
  CursorProvider = {
363
425
  name: "cursor",
@@ -380,7 +442,11 @@ var init_ai_provider = __esm({
380
442
  isProjectLevel: true,
381
443
  // Config is project-level only
382
444
  websiteUrl: "https://cursor.com",
383
- docsUrl: "https://cursor.com/docs"
445
+ docsUrl: "https://cursor.com/docs",
446
+ defaultModel: null,
447
+ // Multi-model IDE, user selects
448
+ supportedModels: [],
449
+ minCliVersion: null
384
450
  };
385
451
  WindsurfProvider = {
386
452
  name: "windsurf",
@@ -403,7 +469,11 @@ var init_ai_provider = __esm({
403
469
  isProjectLevel: true,
404
470
  // Config is project-level only
405
471
  websiteUrl: "https://windsurf.com",
406
- docsUrl: "https://docs.windsurf.com"
472
+ docsUrl: "https://docs.windsurf.com",
473
+ defaultModel: null,
474
+ // Multi-model IDE, user selects
475
+ supportedModels: [],
476
+ minCliVersion: null
407
477
  };
408
478
  Providers = {
409
479
  claude: ClaudeProvider,
@@ -415,6 +485,7 @@ var init_ai_provider = __esm({
415
485
  __name(whichCommand, "whichCommand");
416
486
  __name(getCliVersion, "getCliVersion");
417
487
  __name(detectProvider, "detectProvider");
488
+ __name(validateCliVersion, "validateCliVersion");
418
489
  __name(detectAllProviders, "detectAllProviders");
419
490
  __name(getActiveProvider, "getActiveProvider");
420
491
  __name(hasProviderConfig, "hasProviderConfig");
@@ -49,6 +49,46 @@ var init_fs_helpers = __esm({
49
49
  }
50
50
  });
51
51
 
52
+ // core/schemas/model.ts
53
+ function compareSemver(a, b) {
54
+ const pa = a.split(".").map(Number);
55
+ const pb = b.split(".").map(Number);
56
+ for (let i = 0; i < 3; i++) {
57
+ const va = pa[i] ?? 0;
58
+ const vb = pb[i] ?? 0;
59
+ if (va < vb) return -1;
60
+ if (va > vb) return 1;
61
+ }
62
+ return 0;
63
+ }
64
+ var import_zod, ClaudeModelSchema, GeminiModelSchema, AIModelSchema, ModelMetadataSchema, ModelPreferenceSchema;
65
+ var init_model = __esm({
66
+ "core/schemas/model.ts"() {
67
+ "use strict";
68
+ import_zod = require("zod");
69
+ ClaudeModelSchema = import_zod.z.enum(["opus", "sonnet", "haiku"]);
70
+ GeminiModelSchema = import_zod.z.enum(["2.5-pro", "2.5-flash", "2.0-flash"]);
71
+ AIModelSchema = import_zod.z.string().min(1);
72
+ ModelMetadataSchema = import_zod.z.object({
73
+ /** Provider name (e.g., 'claude', 'gemini') */
74
+ provider: import_zod.z.string(),
75
+ /** Model identifier (e.g., 'opus', 'sonnet', '2.5-pro') */
76
+ model: import_zod.z.string(),
77
+ /** CLI version used */
78
+ cliVersion: import_zod.z.string().optional(),
79
+ /** When this was recorded */
80
+ recordedAt: import_zod.z.string()
81
+ });
82
+ ModelPreferenceSchema = import_zod.z.object({
83
+ /** Preferred model for this project */
84
+ preferredModel: import_zod.z.string().optional(),
85
+ /** Model used for last analysis (for mismatch detection) */
86
+ lastAnalysisModel: ModelMetadataSchema.optional()
87
+ });
88
+ __name(compareSemver, "compareSemver");
89
+ }
90
+ });
91
+
52
92
  // core/utils/provider-cache.ts
53
93
  async function readProviderCache() {
54
94
  try {
@@ -109,7 +149,8 @@ __export(ai_provider_exports, {
109
149
  hasProviderConfig: () => hasProviderConfig,
110
150
  needsCursorRouterRegeneration: () => needsCursorRouterRegeneration,
111
151
  needsWindsurfRouterRegeneration: () => needsWindsurfRouterRegeneration,
112
- selectProvider: () => selectProvider
152
+ selectProvider: () => selectProvider,
153
+ validateCliVersion: () => validateCliVersion
113
154
  });
114
155
  async function whichCommand(command) {
115
156
  try {
@@ -138,12 +179,22 @@ async function detectProvider(provider) {
138
179
  return { installed: false };
139
180
  }
140
181
  const version = await getCliVersion(config.cliCommand);
182
+ const versionWarning = validateCliVersion(provider, version || void 0);
141
183
  return {
142
184
  installed: true,
143
185
  version: version || void 0,
144
- path: cliPath
186
+ path: cliPath,
187
+ versionWarning: versionWarning || void 0
145
188
  };
146
189
  }
190
+ function validateCliVersion(provider, version) {
191
+ const config = Providers[provider];
192
+ if (!config.minCliVersion || !version) return null;
193
+ if (compareSemver(version, config.minCliVersion) < 0) {
194
+ return `\u26A0\uFE0F ${config.displayName} v${version} is below minimum v${config.minCliVersion}. Some features may not work correctly.`;
195
+ }
196
+ return null;
197
+ }
147
198
  async function detectAllProviders(refresh = false) {
148
199
  if (!refresh) {
149
200
  const cached = await readProviderCache();
@@ -305,6 +356,7 @@ var init_ai_provider = __esm({
305
356
  import_node_os2 = __toESM(require("node:os"));
306
357
  import_node_path3 = __toESM(require("node:path"));
307
358
  import_node_util = require("node:util");
359
+ init_model();
308
360
  init_fs_helpers();
309
361
  init_provider_cache();
310
362
  execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
@@ -322,7 +374,10 @@ var init_ai_provider = __esm({
322
374
  projectSettingsFile: "settings.local.json",
323
375
  ignoreFile: ".claudeignore",
324
376
  websiteUrl: "https://www.anthropic.com/claude",
325
- docsUrl: "https://docs.anthropic.com/claude-code"
377
+ docsUrl: "https://docs.anthropic.com/claude-code",
378
+ defaultModel: "sonnet",
379
+ supportedModels: ["opus", "sonnet", "haiku"],
380
+ minCliVersion: "1.0.0"
326
381
  };
327
382
  GeminiProvider = {
328
383
  name: "gemini",
@@ -337,7 +392,10 @@ var init_ai_provider = __esm({
337
392
  projectSettingsFile: "settings.json",
338
393
  ignoreFile: ".geminiignore",
339
394
  websiteUrl: "https://geminicli.com",
340
- docsUrl: "https://geminicli.com/docs"
395
+ docsUrl: "https://geminicli.com/docs",
396
+ defaultModel: "2.5-flash",
397
+ supportedModels: ["2.5-pro", "2.5-flash", "2.0-flash"],
398
+ minCliVersion: "1.0.0"
341
399
  };
342
400
  AntigravityProvider = {
343
401
  name: "antigravity",
@@ -357,7 +415,11 @@ var init_ai_provider = __esm({
357
415
  ignoreFile: ".agentignore",
358
416
  // Assumed
359
417
  websiteUrl: "https://gemini.google.com/app/antigravity",
360
- docsUrl: "https://gemini.google.com/app/antigravity"
418
+ docsUrl: "https://gemini.google.com/app/antigravity",
419
+ defaultModel: null,
420
+ // Platform-managed
421
+ supportedModels: [],
422
+ minCliVersion: null
361
423
  };
362
424
  CursorProvider = {
363
425
  name: "cursor",
@@ -380,7 +442,11 @@ var init_ai_provider = __esm({
380
442
  isProjectLevel: true,
381
443
  // Config is project-level only
382
444
  websiteUrl: "https://cursor.com",
383
- docsUrl: "https://cursor.com/docs"
445
+ docsUrl: "https://cursor.com/docs",
446
+ defaultModel: null,
447
+ // Multi-model IDE, user selects
448
+ supportedModels: [],
449
+ minCliVersion: null
384
450
  };
385
451
  WindsurfProvider = {
386
452
  name: "windsurf",
@@ -403,7 +469,11 @@ var init_ai_provider = __esm({
403
469
  isProjectLevel: true,
404
470
  // Config is project-level only
405
471
  websiteUrl: "https://windsurf.com",
406
- docsUrl: "https://docs.windsurf.com"
472
+ docsUrl: "https://docs.windsurf.com",
473
+ defaultModel: null,
474
+ // Multi-model IDE, user selects
475
+ supportedModels: [],
476
+ minCliVersion: null
407
477
  };
408
478
  Providers = {
409
479
  claude: ClaudeProvider,
@@ -415,6 +485,7 @@ var init_ai_provider = __esm({
415
485
  __name(whichCommand, "whichCommand");
416
486
  __name(getCliVersion, "getCliVersion");
417
487
  __name(detectProvider, "detectProvider");
488
+ __name(validateCliVersion, "validateCliVersion");
418
489
  __name(detectAllProviders, "detectAllProviders");
419
490
  __name(getActiveProvider, "getActiveProvider");
420
491
  __name(hasProviderConfig, "hasProviderConfig");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {