@theia/ai-chat 1.74.0-next.9 → 1.74.1

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 (102) hide show
  1. package/lib/browser/agent-delegation-tool.js +6 -7
  2. package/lib/browser/agent-delegation-tool.js.map +1 -1
  3. package/lib/browser/agent-delegation-tool.spec.js +13 -0
  4. package/lib/browser/agent-delegation-tool.spec.js.map +1 -1
  5. package/lib/browser/chat-request-command-resolution.spec.d.ts +2 -0
  6. package/lib/browser/chat-request-command-resolution.spec.d.ts.map +1 -0
  7. package/lib/browser/chat-request-command-resolution.spec.js +94 -0
  8. package/lib/browser/chat-request-command-resolution.spec.js.map +1 -0
  9. package/lib/browser/chat-session-store-impl.d.ts.map +1 -1
  10. package/lib/browser/chat-session-store-impl.js +2 -0
  11. package/lib/browser/chat-session-store-impl.js.map +1 -1
  12. package/lib/browser/chat-session-store-impl.spec.js +51 -2
  13. package/lib/browser/chat-session-store-impl.spec.js.map +1 -1
  14. package/lib/browser/chat-tool-preference-bindings.d.ts +18 -8
  15. package/lib/browser/chat-tool-preference-bindings.d.ts.map +1 -1
  16. package/lib/browser/chat-tool-preference-bindings.js +27 -28
  17. package/lib/browser/chat-tool-preference-bindings.js.map +1 -1
  18. package/lib/browser/chat-tool-preference-bindings.spec.js +43 -46
  19. package/lib/browser/chat-tool-preference-bindings.spec.js.map +1 -1
  20. package/lib/common/chat-agents.d.ts +8 -0
  21. package/lib/common/chat-agents.d.ts.map +1 -1
  22. package/lib/common/chat-agents.js +35 -1
  23. package/lib/common/chat-agents.js.map +1 -1
  24. package/lib/common/chat-agents.spec.js +94 -0
  25. package/lib/common/chat-agents.spec.js.map +1 -1
  26. package/lib/common/chat-auto-save.spec.js +13 -0
  27. package/lib/common/chat-auto-save.spec.js.map +1 -1
  28. package/lib/common/chat-content-deserializer.d.ts.map +1 -1
  29. package/lib/common/chat-content-deserializer.js +4 -0
  30. package/lib/common/chat-content-deserializer.js.map +1 -1
  31. package/lib/common/chat-model-serialization.d.ts +12 -1
  32. package/lib/common/chat-model-serialization.d.ts.map +1 -1
  33. package/lib/common/chat-model-serialization.js.map +1 -1
  34. package/lib/common/chat-model-serialization.spec.js +29 -0
  35. package/lib/common/chat-model-serialization.spec.js.map +1 -1
  36. package/lib/common/chat-model.d.ts +105 -2
  37. package/lib/common/chat-model.d.ts.map +1 -1
  38. package/lib/common/chat-model.js +159 -3
  39. package/lib/common/chat-model.js.map +1 -1
  40. package/lib/common/chat-model.spec.d.ts +2 -0
  41. package/lib/common/chat-model.spec.d.ts.map +1 -0
  42. package/lib/common/chat-model.spec.js +42 -0
  43. package/lib/common/chat-model.spec.js.map +1 -0
  44. package/lib/common/chat-request-parser.d.ts +9 -1
  45. package/lib/common/chat-request-parser.d.ts.map +1 -1
  46. package/lib/common/chat-request-parser.js +54 -3
  47. package/lib/common/chat-request-parser.js.map +1 -1
  48. package/lib/common/chat-request-parser.spec.js +333 -0
  49. package/lib/common/chat-request-parser.spec.js.map +1 -1
  50. package/lib/common/chat-response-model.spec.js +31 -0
  51. package/lib/common/chat-response-model.spec.js.map +1 -1
  52. package/lib/common/chat-service-deletion.spec.js +43 -0
  53. package/lib/common/chat-service-deletion.spec.js.map +1 -1
  54. package/lib/common/chat-service-pinned-agent.spec.js +52 -2
  55. package/lib/common/chat-service-pinned-agent.spec.js.map +1 -1
  56. package/lib/common/chat-service-session-events.spec.d.ts +2 -0
  57. package/lib/common/chat-service-session-events.spec.d.ts.map +1 -0
  58. package/lib/common/chat-service-session-events.spec.js +130 -0
  59. package/lib/common/chat-service-session-events.spec.js.map +1 -0
  60. package/lib/common/chat-service.d.ts +3 -0
  61. package/lib/common/chat-service.d.ts.map +1 -1
  62. package/lib/common/chat-service.js +60 -6
  63. package/lib/common/chat-service.js.map +1 -1
  64. package/lib/common/chat-service.spec.d.ts +2 -0
  65. package/lib/common/chat-service.spec.d.ts.map +1 -0
  66. package/lib/common/chat-service.spec.js +177 -0
  67. package/lib/common/chat-service.spec.js.map +1 -0
  68. package/lib/common/chat-session-status.spec.d.ts +2 -0
  69. package/lib/common/chat-session-status.spec.d.ts.map +1 -0
  70. package/lib/common/chat-session-status.spec.js +213 -0
  71. package/lib/common/chat-session-status.spec.js.map +1 -0
  72. package/lib/common/chat-session-store.d.ts +8 -0
  73. package/lib/common/chat-session-store.d.ts.map +1 -1
  74. package/lib/common/tool-call-response-content.spec.js +36 -0
  75. package/lib/common/tool-call-response-content.spec.js.map +1 -1
  76. package/package.json +11 -11
  77. package/src/browser/agent-delegation-tool.spec.ts +16 -0
  78. package/src/browser/agent-delegation-tool.ts +7 -7
  79. package/src/browser/chat-request-command-resolution.spec.ts +117 -0
  80. package/src/browser/chat-session-store-impl.spec.ts +62 -2
  81. package/src/browser/chat-session-store-impl.ts +2 -0
  82. package/src/browser/chat-tool-preference-bindings.spec.ts +43 -48
  83. package/src/browser/chat-tool-preference-bindings.ts +42 -30
  84. package/src/common/chat-agents.spec.ts +112 -2
  85. package/src/common/chat-agents.ts +44 -1
  86. package/src/common/chat-auto-save.spec.ts +18 -1
  87. package/src/common/chat-content-deserializer.ts +11 -0
  88. package/src/common/chat-model-serialization.spec.ts +38 -0
  89. package/src/common/chat-model-serialization.ts +12 -1
  90. package/src/common/chat-model.spec.ts +42 -0
  91. package/src/common/chat-model.ts +241 -3
  92. package/src/common/chat-request-parser.spec.ts +401 -1
  93. package/src/common/chat-request-parser.ts +60 -5
  94. package/src/common/chat-response-model.spec.ts +41 -1
  95. package/src/common/chat-service-deletion.spec.ts +52 -0
  96. package/src/common/chat-service-pinned-agent.spec.ts +58 -2
  97. package/src/common/chat-service-session-events.spec.ts +161 -0
  98. package/src/common/chat-service.spec.ts +211 -0
  99. package/src/common/chat-service.ts +64 -8
  100. package/src/common/chat-session-status.spec.ts +280 -0
  101. package/src/common/chat-session-store.ts +8 -0
  102. package/src/common/tool-call-response-content.spec.ts +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-model.spec.d.ts","sourceRoot":"","sources":["../../src/common/chat-model.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const chai_1 = require("chai");
19
+ const chat_model_1 = require("./chat-model");
20
+ describe('CompactionChatResponseContent', () => {
21
+ it('round-trips through serialization', () => {
22
+ const original = new chat_model_1.CompactionChatResponseContentImpl('anthropic', { block: 'opaque' }, 'summary text');
23
+ const serialized = original.toSerializable();
24
+ (0, chai_1.expect)(serialized.kind).to.equal('compaction');
25
+ const restored = new chat_model_1.CompactionChatResponseContentImpl(serialized.data.provider, serialized.data.data, serialized.data.summary);
26
+ (0, chai_1.expect)(restored.provider).to.equal('anthropic');
27
+ (0, chai_1.expect)(restored.summary).to.equal('summary text');
28
+ (0, chai_1.expect)(restored.data).to.deep.equal({ block: 'opaque' });
29
+ });
30
+ it('produces a compaction language model message', () => {
31
+ const content = new chat_model_1.CompactionChatResponseContentImpl('openai-responses', { item: 'x' });
32
+ const message = content.toLanguageModelMessage();
33
+ (0, chai_1.expect)(message).to.deep.equal({ actor: 'ai', type: 'compaction', provider: 'openai-responses', data: { item: 'x' }, summary: undefined });
34
+ });
35
+ it('is excluded from plain-text history but offers a display string', () => {
36
+ const content = new chat_model_1.CompactionChatResponseContentImpl('anthropic', {}, 'sum');
37
+ (0, chai_1.expect)(content.asString()).to.equal(undefined);
38
+ (0, chai_1.expect)(content.asDisplayString()).to.equal('sum');
39
+ (0, chai_1.expect)(chat_model_1.CompactionChatResponseContent.is(content)).to.equal(true);
40
+ });
41
+ });
42
+ //# sourceMappingURL=chat-model.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-model.spec.js","sourceRoot":"","sources":["../../src/common/chat-model.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,+BAA8B;AAC9B,6CAAgG;AAEhG,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,QAAQ,GAAG,IAAI,8CAAiC,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,cAAc,CAAC,CAAC;QACzG,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC7C,IAAA,aAAM,EAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,8CAAiC,CAClD,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7E,IAAA,aAAM,EAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAChD,IAAA,aAAM,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAClD,IAAA,aAAM,EAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,OAAO,GAAG,IAAI,8CAAiC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACzF,MAAM,OAAO,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC;QACjD,IAAA,aAAM,EAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9I,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACvE,MAAM,OAAO,GAAG,IAAI,8CAAiC,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9E,IAAA,aAAM,EAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAA,aAAM,EAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClD,IAAA,aAAM,EAAC,0CAA6B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -2,7 +2,7 @@ import { ChatAgentService } from './chat-agent-service';
2
2
  import { ChatAgentLocation } from './chat-agents';
3
3
  import { ChatContext, ChatRequest } from './chat-model';
4
4
  import { ParsedChatRequestVariablePart, ParsedChatRequest, ParsedChatRequestPart } from './parsed-chat-request';
5
- import { AIVariable, AIVariableService, ToolInvocationRegistry, ToolRequest } from '@theia/ai-core';
5
+ import { AIVariable, AIVariableService, PromptService, ToolInvocationRegistry, ToolRequest } from '@theia/ai-core';
6
6
  import { ILogger } from '@theia/core';
7
7
  export declare const ChatRequestParser: unique symbol;
8
8
  export interface ChatRequestParser {
@@ -13,6 +13,7 @@ export declare class ChatRequestParserImpl implements ChatRequestParser {
13
13
  private readonly variableService;
14
14
  private readonly toolInvocationRegistry;
15
15
  private readonly logger;
16
+ protected readonly promptService: PromptService;
16
17
  constructor(agentService: ChatAgentService, variableService: AIVariableService, toolInvocationRegistry: ToolInvocationRegistry, logger: ILogger);
17
18
  parseChatRequest(request: ChatRequest, location: ChatAgentLocation, context: ChatContext): Promise<ParsedChatRequest>;
18
19
  protected parseParts(request: ChatRequest, location: ChatAgentLocation): {
@@ -34,6 +35,13 @@ export declare class ChatRequestParserImpl implements ChatRequestParser {
34
35
  * The prompt variable resolver will handle the actual resolution.
35
36
  */
36
37
  protected tryToParseCommand(message: string, offset: number, _parts: ReadonlyArray<ParsedChatRequestPart>): ParsedChatRequestVariablePart | undefined;
38
+ private findNextCommandOffset;
39
+ /**
40
+ * Whether a `/name` token should be treated as a command. Only names that actually resolve to a
41
+ * command or prompt fragment are accepted, which keeps unknown `/word` tokens (e.g. `/tmp`,
42
+ * `/path/to/file`) as plain text.
43
+ */
44
+ protected isCommandCandidate(commandName: string): boolean;
37
45
  private tryToParseFunction;
38
46
  }
39
47
  //# sourceMappingURL=chat-request-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-request-parser.d.ts","sourceRoot":"","sources":["../../src/common/chat-request-parser.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAMH,6BAA6B,EAI7B,iBAAiB,EACjB,qBAAqB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACH,UAAU,EAAE,iBAAiB,EAAmF,sBAAsB,EAAE,WAAW,EACtJ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAUtC,eAAO,MAAM,iBAAiB,eAA8B,CAAC;AAC7D,MAAM,WAAW,iBAAiB;IAC9B,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACzH;AAQD,qBACa,qBAAsB,YAAW,iBAAiB;IAE7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHG,YAAY,EAAE,gBAAgB,EAC7B,eAAe,EAAE,iBAAiB,EAC7B,sBAAsB,EAAE,sBAAsB,EAC7D,MAAM,EAAE,OAAO;IAG/C,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiC3H,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,GAAG;QACrE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QAC/B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACvC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;KACtC;IA8FD;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAkBtC,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,kBAAkB;IAiB1B;;;;;OAKG;IACH,SAAS,CAAC,iBAAiB,CACvB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,aAAa,CAAC,qBAAqB,CAAC,GAC7C,6BAA6B,GAAG,SAAS;IAa5C,OAAO,CAAC,kBAAkB;CAkB7B"}
1
+ {"version":3,"file":"chat-request-parser.d.ts","sourceRoot":"","sources":["../../src/common/chat-request-parser.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAMH,6BAA6B,EAI7B,iBAAiB,EACjB,qBAAqB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACH,UAAU,EAAE,iBAAiB,EAAmF,aAAa,EAAE,sBAAsB,EAAE,WAAW,EACrK,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AActC,eAAO,MAAM,iBAAiB,eAA8B,CAAC;AAC7D,MAAM,WAAW,iBAAiB;IAC9B,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACzH;AAQD,qBACa,qBAAsB,YAAW,iBAAiB;IAM7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAN5C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;gBAGD,YAAY,EAAE,gBAAgB,EAC7B,eAAe,EAAE,iBAAiB,EAC7B,sBAAsB,EAAE,sBAAsB,EAC7D,MAAM,EAAE,OAAO;IAG/C,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiC3H,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,GAAG;QACrE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QAC/B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACvC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;KACtC;IA+FD;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAkBtC,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,kBAAkB;IAiB1B;;;;;OAKG;IACH,SAAS,CAAC,iBAAiB,CACvB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,aAAa,CAAC,qBAAqB,CAAC,GAC7C,6BAA6B,GAAG,SAAS;IAsC5C,OAAO,CAAC,qBAAqB;IAY7B;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAI1D,OAAO,CAAC,kBAAkB;CAkB7B"}
@@ -33,7 +33,11 @@ const agentReg = /^@([\w_\-\.]+)(?=(\s|$|\b))/i; // An @-agent
33
33
  const functionReg = /^~(\??[\w_\-\.]+)(?=(\s|$|\b))/i;
34
34
  const functionPromptFormatReg = /^\~\{\s*(.*?)\s*\}/i;
35
35
  const variableReg = /^#([\w_\-]+)(?::([\w_\-_\/\\.:]+))?(?=(\s|$|\b))/i; // A #-variable with an optional : arg (#file:workspace/path/name.ext)
36
- const commandReg = /^\/([\w_\-]+)(?:\s+(.+?))?(?=\s*$)/; // A /-command with optional arguments (/commandname arg1 arg2)
36
+ // A /-command (/commandname) with optional arguments parsed separately. The command name must be
37
+ // terminated by whitespace or the end of the input, so that path segments such as `/home/user` are
38
+ // not mistaken for a command.
39
+ const commandReg = /^\/([\w_\-]+)(?=\s|$)/;
40
+ const nextCommandReg = /\s+\/([\w_\-]+)(?=\s|$)/g;
37
41
  exports.ChatRequestParser = Symbol('ChatRequestParser');
38
42
  function offsetRange(start, endExclusive) {
39
43
  if (start > endExclusive) {
@@ -131,6 +135,7 @@ let ChatRequestParserImpl = class ChatRequestParserImpl {
131
135
  parts.push(new parsed_chat_request_1.ParsedChatRequestTextPart(offsetRange(previousPartEnd, i), message.slice(previousPartEnd, i)));
132
136
  }
133
137
  parts.push(newPart);
138
+ i = newPart.range.endExclusive - 1;
134
139
  }
135
140
  }
136
141
  const lastPart = parts.at(-1);
@@ -206,11 +211,53 @@ let ChatRequestParserImpl = class ChatRequestParserImpl {
206
211
  if (!nextCommandMatch) {
207
212
  return;
208
213
  }
209
- const [full, commandName, commandArgs] = nextCommandMatch;
210
- const commandRange = offsetRange(offset, offset + full.length);
214
+ const [commandText, commandName] = nextCommandMatch;
215
+ if (!this.isCommandCandidate(commandName)) {
216
+ // Not a command we know about, so leave the text alone. Otherwise anything the user
217
+ // types after a `/word` token, e.g. a Unix path, would be swallowed as command
218
+ // arguments and silently dropped when the non-existing command fails to resolve.
219
+ return;
220
+ }
221
+ let commandEnd = commandText.length;
222
+ let commandArgs;
223
+ // Arguments never span multiple lines: a command only consumes the remainder of its own line.
224
+ const lineBreakOffset = message.indexOf('\n', commandEnd);
225
+ const lineEnd = lineBreakOffset === -1 ? message.length : lineBreakOffset;
226
+ const nextCommandOffset = this.findNextCommandOffset(message, commandEnd, lineEnd);
227
+ const argsEnd = nextCommandOffset ?? lineEnd;
228
+ const rawArgs = message.slice(commandEnd, argsEnd);
229
+ const args = rawArgs.trim();
230
+ if (args) {
231
+ commandArgs = args;
232
+ // Advance the consumed range only up to the end of the trimmed argument, not up to the
233
+ // next command. This keeps the whitespace between the argument and a following command
234
+ // out of this part's range, so parseParts emits it as a separator text part. Otherwise
235
+ // the two resolved prompt fragments would run into each other with no space between them.
236
+ commandEnd = argsEnd - (rawArgs.length - rawArgs.trimEnd().length);
237
+ }
238
+ const commandRange = offsetRange(offset, offset + commandEnd);
211
239
  const variableArg = commandArgs ? `${commandName}|${commandArgs}` : commandName;
212
240
  return new parsed_chat_request_1.ParsedChatRequestVariablePart(commandRange, 'prompt', variableArg);
213
241
  }
242
+ findNextCommandOffset(message, startOffset, endOffset) {
243
+ nextCommandReg.lastIndex = startOffset;
244
+ let match = nextCommandReg.exec(message);
245
+ while (match && match.index < endOffset) {
246
+ if (this.isCommandCandidate(match[1])) {
247
+ return match.index + match[0].indexOf(parsed_chat_request_1.chatSubcommandLeader);
248
+ }
249
+ match = nextCommandReg.exec(message);
250
+ }
251
+ return undefined;
252
+ }
253
+ /**
254
+ * Whether a `/name` token should be treated as a command. Only names that actually resolve to a
255
+ * command or prompt fragment are accepted, which keeps unknown `/word` tokens (e.g. `/tmp`,
256
+ * `/path/to/file`) as plain text.
257
+ */
258
+ isCommandCandidate(commandName) {
259
+ return this.promptService.isKnownCommand(commandName);
260
+ }
214
261
  tryToParseFunction(message, offset) {
215
262
  // Support both the chat and prompt formats for functions
216
263
  const nextFunctionMatch = message.match(functionPromptFormatReg) || message.match(functionReg);
@@ -228,6 +275,10 @@ let ChatRequestParserImpl = class ChatRequestParserImpl {
228
275
  }
229
276
  };
230
277
  exports.ChatRequestParserImpl = ChatRequestParserImpl;
278
+ tslib_1.__decorate([
279
+ (0, inversify_1.inject)(ai_core_1.PromptService),
280
+ tslib_1.__metadata("design:type", Object)
281
+ ], ChatRequestParserImpl.prototype, "promptService", void 0);
231
282
  exports.ChatRequestParserImpl = ChatRequestParserImpl = tslib_1.__decorate([
232
283
  (0, inversify_1.injectable)(),
233
284
  tslib_1.__param(0, (0, inversify_1.inject)(chat_agent_service_1.ChatAgentService)),
@@ -1 +1 @@
1
- {"version":3,"file":"chat-request-parser.js","sourceRoot":"","sources":["../../src/common/chat-request-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-request-parser.js","sourceRoot":"","sources":["../../src/common/chat-request-parser.ts"],"names":[],"mappings":"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"}
@@ -25,11 +25,21 @@ const core_1 = require("@theia/core");
25
25
  const parsed_chat_request_1 = require("./parsed-chat-request");
26
26
  const agent_delegation_tool_1 = require("../browser/agent-delegation-tool");
27
27
  describe('ChatRequestParserImpl', () => {
28
+ /** Command names the stubbed `PromptService` knows about. Anything else is not a command. */
29
+ const KNOWN_COMMANDS = ['hello', 'explain', 'compare', 'cmd', 'summarize', 'skill-one', 'skill-two'];
30
+ /** Prompt fragments that are not marked as commands, but can still be invoked by their id. */
31
+ const KNOWN_FRAGMENT_IDS = ['coder-system'];
32
+ const promptService = {
33
+ isKnownCommand: (name) => KNOWN_COMMANDS.includes(name) || KNOWN_FRAGMENT_IDS.includes(name),
34
+ getCommands: () => KNOWN_COMMANDS.map(name => ({ id: `command-${name}`, template: '', isCommand: true, commandName: name }))
35
+ };
28
36
  const chatAgentService = sinon.createStubInstance(chat_agent_service_1.ChatAgentServiceImpl);
29
37
  const variableService = sinon.createStubInstance(ai_core_1.DefaultAIVariableService);
30
38
  const toolInvocationRegistry = sinon.createStubInstance(ai_core_1.ToolInvocationRegistryImpl);
31
39
  const logger = sinon.createStubInstance(core_1.Logger);
32
40
  const parser = new chat_request_parser_1.ChatRequestParserImpl(chatAgentService, variableService, toolInvocationRegistry, logger);
41
+ // The parser injects the PromptService as a property, so it has to be assigned manually here.
42
+ parser.promptService = promptService;
33
43
  beforeEach(() => {
34
44
  // Reset our stubs before each test
35
45
  sinon.reset();
@@ -235,6 +245,58 @@ describe('ChatRequestParserImpl', () => {
235
245
  const varPart = result.parts[0];
236
246
  (0, chai_1.expect)(varPart.variableArg).to.equal('cmd|"arg with \\"quote\\"" other');
237
247
  });
248
+ it('parses multiple commands in one message', async () => {
249
+ const req = {
250
+ text: '/skill-one /skill-two'
251
+ };
252
+ const context = { variables: [] };
253
+ const result = await parser.parseChatRequest(req, chat_agents_1.ChatAgentLocation.Panel, context);
254
+ (0, chai_1.expect)(result.parts.length).to.equal(3);
255
+ const firstCommand = result.parts[0];
256
+ const separator = result.parts[1];
257
+ const secondCommand = result.parts[2];
258
+ (0, chai_1.expect)(firstCommand.variableName).to.equal('prompt');
259
+ (0, chai_1.expect)(firstCommand.variableArg).to.equal('skill-one');
260
+ (0, chai_1.expect)(separator.text).to.equal(' ');
261
+ (0, chai_1.expect)(secondCommand.variableName).to.equal('prompt');
262
+ (0, chai_1.expect)(secondCommand.variableArg).to.equal('skill-two');
263
+ });
264
+ it('inserts a separator between two argument-taking commands', async () => {
265
+ const req = {
266
+ text: '/summarize foo /hello bar'
267
+ };
268
+ const context = { variables: [] };
269
+ const result = await parser.parseChatRequest(req, chat_agents_1.ChatAgentLocation.Panel, context);
270
+ (0, chai_1.expect)(result.parts.length).to.equal(3);
271
+ const firstCommand = result.parts[0];
272
+ const separator = result.parts[1];
273
+ const secondCommand = result.parts[2];
274
+ (0, chai_1.expect)(firstCommand.variableArg).to.equal('summarize|foo');
275
+ (0, chai_1.expect)(separator.kind).to.equal('text');
276
+ (0, chai_1.expect)(separator.text).to.equal(' ');
277
+ (0, chai_1.expect)(secondCommand.variableArg).to.equal('hello|bar');
278
+ });
279
+ it('keeps path-like slash arguments as command arguments', async () => {
280
+ const req = {
281
+ text: '/explain /path/to/file'
282
+ };
283
+ const context = { variables: [] };
284
+ const result = await parser.parseChatRequest(req, chat_agents_1.ChatAgentLocation.Panel, context);
285
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
286
+ const varPart = result.parts[0];
287
+ (0, chai_1.expect)(varPart.variableName).to.equal('prompt');
288
+ (0, chai_1.expect)(varPart.variableArg).to.equal('explain|/path/to/file');
289
+ });
290
+ it('does not treat path segments as commands', async () => {
291
+ const req = {
292
+ text: 'please look at /home/user/notes.txt and fix the bug'
293
+ };
294
+ const context = { variables: [] };
295
+ const result = await parser.parseChatRequest(req, chat_agents_1.ChatAgentLocation.Panel, context);
296
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
297
+ (0, chai_1.expect)(result.parts[0].kind).to.equal('text');
298
+ (0, chai_1.expect)(result.parts[0].text).to.equal(req.text);
299
+ });
238
300
  it('treats the first @agent mention as the selector and does not allow later mentions to override it', async () => {
239
301
  const createAgent = (id) => ({
240
302
  id,
@@ -388,6 +450,277 @@ describe('ChatRequestParserImpl', () => {
388
450
  (0, chai_1.expect)(result.deferredToolIds?.has('eagerTool')).to.be.false;
389
451
  });
390
452
  });
453
+ describe('slash command disambiguation', () => {
454
+ const parse = (text) => parser.parseChatRequest({ text }, chat_agents_1.ChatAgentLocation.Panel, { variables: [] });
455
+ /** Every character of the input has to be covered by exactly one part, in order and without gaps. */
456
+ const expectFullCoverage = (parts, text) => {
457
+ let expectedStart = 0;
458
+ for (const part of parts) {
459
+ (0, chai_1.expect)(part.range.start, `part starting at ${part.range.start} does not continue at ${expectedStart}`).to.equal(expectedStart);
460
+ expectedStart = part.range.endExclusive;
461
+ }
462
+ (0, chai_1.expect)(expectedStart, 'parts do not cover the whole message').to.equal(text.length);
463
+ };
464
+ const expectPlainText = async (text) => {
465
+ const result = await parse(text);
466
+ (0, chai_1.expect)(result.parts.map(p => p.kind), `expected only text parts for ${JSON.stringify(text)}`).to.deep.equal(['text']);
467
+ (0, chai_1.expect)(result.parts[0].text).to.equal(text);
468
+ expectFullCoverage(result.parts, text);
469
+ };
470
+ describe('unknown commands stay plain text', () => {
471
+ const unknownCommandInputs = [
472
+ 'please look at /home/user/notes.txt and fix the bug',
473
+ '/home/user/notes.txt is broken',
474
+ 'read /usr/local/bin/theia',
475
+ 'the file is at /etc/hosts',
476
+ 'compare /tmp/a.txt with /tmp/b.txt',
477
+ 'run cd /home && ls',
478
+ 'see /usr/lib/node/foo.js:12 for the stack trace',
479
+ 'what does the option --foo /bar do?',
480
+ '/does-not-exist do something',
481
+ '/tmp',
482
+ 'move it to /tmp',
483
+ 'the separator is / on Unix'
484
+ ];
485
+ unknownCommandInputs.forEach(text => {
486
+ it(`keeps ${JSON.stringify(text)} as plain text`, () => expectPlainText(text));
487
+ });
488
+ it('does not drop any user text when a path follows a known command name prefix', async () => {
489
+ // `/summarizes` is not a known command, even though `/summarize` is.
490
+ await expectPlainText('/summarizes the file');
491
+ });
492
+ it('does not treat a known command name as a command when it is a path segment', async () => {
493
+ // `summarize` is known, but `/summarize/foo` is a path, not a command invocation.
494
+ await expectPlainText('/summarize/foo is a path');
495
+ });
496
+ it('does not treat a known command name followed by punctuation as a command', async () => {
497
+ await expectPlainText('did you mean /summarize?');
498
+ });
499
+ });
500
+ describe('slashes that are not command leaders', () => {
501
+ const nonLeaderInputs = [
502
+ 'A: 10/20 and B: 30/40',
503
+ 'use and/or here',
504
+ '2026/08/04 is the date',
505
+ 'see https://example.com/foo/bar for details',
506
+ 'the regex is a\\/b'
507
+ ];
508
+ nonLeaderInputs.forEach(text => {
509
+ it(`keeps ${JSON.stringify(text)} as plain text`, () => expectPlainText(text));
510
+ });
511
+ });
512
+ describe('known commands still parse', () => {
513
+ it('parses a known command without arguments', async () => {
514
+ const text = '/summarize';
515
+ const result = await parse(text);
516
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
517
+ const command = result.parts[0];
518
+ (0, chai_1.expect)(command.variableName).to.equal('prompt');
519
+ (0, chai_1.expect)(command.variableArg).to.equal('summarize');
520
+ expectFullCoverage(result.parts, text);
521
+ });
522
+ it('parses a known command with arguments', async () => {
523
+ const text = '/summarize foo bar';
524
+ const result = await parse(text);
525
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
526
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo bar');
527
+ expectFullCoverage(result.parts, text);
528
+ });
529
+ it('keeps a path as the argument of a known command', async () => {
530
+ const text = '/summarize /home/user/notes.txt';
531
+ const result = await parse(text);
532
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
533
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|/home/user/notes.txt');
534
+ expectFullCoverage(result.parts, text);
535
+ });
536
+ it('keeps an unknown slash token inside the arguments of a known command', async () => {
537
+ const text = '/summarize foo /unknown bar';
538
+ const result = await parse(text);
539
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
540
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo /unknown bar');
541
+ expectFullCoverage(result.parts, text);
542
+ });
543
+ it('parses a known command in the middle of a message', async () => {
544
+ const text = 'please /summarize this';
545
+ const result = await parse(text);
546
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['text', 'var']);
547
+ (0, chai_1.expect)(result.parts[0].text).to.equal('please ');
548
+ (0, chai_1.expect)(result.parts[1].variableArg).to.equal('summarize|this');
549
+ expectFullCoverage(result.parts, text);
550
+ });
551
+ it('parses two adjacent known commands', async () => {
552
+ const text = '/skill-one /skill-two';
553
+ const result = await parse(text);
554
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
555
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('skill-one');
556
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' ');
557
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('skill-two');
558
+ expectFullCoverage(result.parts, text);
559
+ });
560
+ it('separates two argument-taking known commands', async () => {
561
+ const text = '/summarize foo /explain bar';
562
+ const result = await parse(text);
563
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
564
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo');
565
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' ');
566
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('explain|bar');
567
+ expectFullCoverage(result.parts, text);
568
+ });
569
+ it('parses the same command twice, each with its own argument', async () => {
570
+ const text = '/hello Klaus /hello Maria';
571
+ const result = await parse(text);
572
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
573
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello|Klaus');
574
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' ');
575
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello|Maria');
576
+ expectFullCoverage(result.parts, text);
577
+ });
578
+ it('parses the same command three times', async () => {
579
+ const text = '/hello Klaus /hello Maria /hello Bob';
580
+ const result = await parse(text);
581
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var', 'text', 'var']);
582
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello|Klaus');
583
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello|Maria');
584
+ (0, chai_1.expect)(result.parts[4].variableArg).to.equal('hello|Bob');
585
+ expectFullCoverage(result.parts, text);
586
+ });
587
+ it('parses the same command twice without arguments', async () => {
588
+ const text = '/hello /hello';
589
+ const result = await parse(text);
590
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
591
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello');
592
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' ');
593
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello');
594
+ expectFullCoverage(result.parts, text);
595
+ });
596
+ it('accepts a prompt fragment id as a command', async () => {
597
+ const text = '/coder-system';
598
+ const result = await parse(text);
599
+ (0, chai_1.expect)(result.parts.length).to.equal(1);
600
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('coder-system');
601
+ });
602
+ it('keeps trailing whitespace out of the command part', async () => {
603
+ const text = '/summarize ';
604
+ const result = await parse(text);
605
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text']);
606
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize');
607
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' ');
608
+ expectFullCoverage(result.parts, text);
609
+ });
610
+ it('trims whitespace around arguments', async () => {
611
+ const text = '/summarize \t foo \t ';
612
+ const result = await parse(text);
613
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo');
614
+ expectFullCoverage(result.parts, text);
615
+ });
616
+ });
617
+ describe('arguments do not span multiple lines', () => {
618
+ it('does not consume the following line for a command without arguments', async () => {
619
+ const text = '/summarize\nsecond line';
620
+ const result = await parse(text);
621
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text']);
622
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize');
623
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\nsecond line');
624
+ expectFullCoverage(result.parts, text);
625
+ });
626
+ it('does not consume the following line for a command with arguments', async () => {
627
+ const text = '/summarize foo\nsecond line\nthird line';
628
+ const result = await parse(text);
629
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text']);
630
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo');
631
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\nsecond line\nthird line');
632
+ expectFullCoverage(result.parts, text);
633
+ });
634
+ it('handles CRLF line endings', async () => {
635
+ const text = '/summarize foo\r\nsecond line';
636
+ const result = await parse(text);
637
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text']);
638
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo');
639
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\r\nsecond line');
640
+ expectFullCoverage(result.parts, text);
641
+ });
642
+ it('parses a command on a later line', async () => {
643
+ const text = 'first line\n/summarize foo\nthird line';
644
+ const result = await parse(text);
645
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['text', 'var', 'text']);
646
+ (0, chai_1.expect)(result.parts[0].text).to.equal('first line\n');
647
+ (0, chai_1.expect)(result.parts[1].variableArg).to.equal('summarize|foo');
648
+ (0, chai_1.expect)(result.parts[2].text).to.equal('\nthird line');
649
+ expectFullCoverage(result.parts, text);
650
+ });
651
+ it('parses one command per line', async () => {
652
+ const text = '/summarize foo\n/explain bar';
653
+ const result = await parse(text);
654
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
655
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('summarize|foo');
656
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\n');
657
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('explain|bar');
658
+ expectFullCoverage(result.parts, text);
659
+ });
660
+ it('parses the same command on consecutive lines', async () => {
661
+ const text = '/hello Klaus\n/hello Maria';
662
+ const result = await parse(text);
663
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
664
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello|Klaus');
665
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\n');
666
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello|Maria');
667
+ expectFullCoverage(result.parts, text);
668
+ });
669
+ it('keeps a blank line between two commands', async () => {
670
+ const text = '/hello Klaus\n\n/hello Maria';
671
+ const result = await parse(text);
672
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var']);
673
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello|Klaus');
674
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\n\n');
675
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello|Maria');
676
+ expectFullCoverage(result.parts, text);
677
+ });
678
+ it('mixes a line break with a repetition on the same line', async () => {
679
+ const text = '/hello Klaus\n/hello Maria and /hello Bob';
680
+ const result = await parse(text);
681
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text', 'var', 'text', 'var']);
682
+ (0, chai_1.expect)(result.parts[0].variableArg).to.equal('hello|Klaus');
683
+ (0, chai_1.expect)(result.parts[1].text).to.equal('\n');
684
+ (0, chai_1.expect)(result.parts[2].variableArg).to.equal('hello|Maria and');
685
+ (0, chai_1.expect)(result.parts[3].text).to.equal(' ');
686
+ (0, chai_1.expect)(result.parts[4].variableArg).to.equal('hello|Bob');
687
+ expectFullCoverage(result.parts, text);
688
+ });
689
+ it('keeps a multi-line paste containing paths untouched', async () => {
690
+ await expectPlainText('here is a stack trace:\n at /usr/lib/node/foo.js:12\nplease fix it');
691
+ });
692
+ });
693
+ describe('interaction with other request parts', () => {
694
+ it('does not turn a path into a command when it follows a variable', async () => {
695
+ const text = '#file:/path/to/file.ext look at /home/user/notes.txt';
696
+ const result = await parse(text);
697
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['var', 'text']);
698
+ (0, chai_1.expect)(result.parts[0].variableName).to.equal('file');
699
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' look at /home/user/notes.txt');
700
+ expectFullCoverage(result.parts, text);
701
+ });
702
+ it('does not turn a path into a command when it follows an agent mention', async () => {
703
+ chatAgentService.getAgents.returns([{
704
+ id: 'agentA',
705
+ name: 'agentA',
706
+ description: '',
707
+ tags: [],
708
+ variables: [],
709
+ prompts: [],
710
+ agentSpecificVariables: [],
711
+ functions: [],
712
+ languageModelRequirements: [],
713
+ locations: [chat_agents_1.ChatAgentLocation.Panel],
714
+ invoke: async () => undefined
715
+ }]);
716
+ const text = '@agentA please read /etc/hosts';
717
+ const result = await parse(text);
718
+ (0, chai_1.expect)(result.parts.map(p => p.kind)).to.deep.equal(['agent', 'text']);
719
+ (0, chai_1.expect)(result.parts[1].text).to.equal(' please read /etc/hosts');
720
+ expectFullCoverage(result.parts, text);
721
+ });
722
+ });
723
+ });
391
724
  describe('parsed chat request part kind assignments', () => {
392
725
  it('ParsedChatRequestTextPart has kind assigned at runtime', () => {
393
726
  const part = new parsed_chat_request_1.ParsedChatRequestTextPart({ start: 0, endExclusive: 5 }, 'hello');