@sprucelabs/spruce-cli 28.1.4 → 28.2.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 (71) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/build/.spruce/errors/errors.types.d.ts +22 -0
  3. package/build/.spruce/errors/options.types.d.ts +4 -1
  4. package/build/.spruce/errors/spruceCli/agentAlreadyRegistered.schema.d.ts +3 -0
  5. package/build/.spruce/errors/spruceCli/agentAlreadyRegistered.schema.js +21 -0
  6. package/build/.spruce/errors/spruceCli/agentAlreadyRegistered.schema.js.map +1 -0
  7. package/build/__tests__/behavioral/agents/RegisteringAnAgentAtBoot.test.d.ts +15 -0
  8. package/build/__tests__/behavioral/agents/RegisteringAnAgentAtBoot.test.js +94 -0
  9. package/build/__tests__/behavioral/agents/RegisteringAnAgentAtBoot.test.js.map +1 -0
  10. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js +0 -7
  11. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js.map +1 -1
  12. package/build/__tests__/behavioral/{SettingRemote.test.d.ts → remote/SettingRemote.test.d.ts} +2 -2
  13. package/build/__tests__/behavioral/{SettingRemote.test.js → remote/SettingRemote.test.js} +2 -2
  14. package/build/__tests__/behavioral/remote/SettingRemote.test.js.map +1 -0
  15. package/build/__tests__/behavioral/remote/SettingRemoteDoesNotAskTwice.test.d.ts +10 -0
  16. package/build/__tests__/behavioral/remote/SettingRemoteDoesNotAskTwice.test.js +67 -0
  17. package/build/__tests__/behavioral/remote/SettingRemoteDoesNotAskTwice.test.js.map +1 -0
  18. package/build/errors/SpruceError.js +3 -0
  19. package/build/errors/SpruceError.js.map +1 -1
  20. package/build/errors/agentAlreadyRegistered.builder.d.ts +13 -0
  21. package/build/errors/agentAlreadyRegistered.builder.js +16 -0
  22. package/build/errors/agentAlreadyRegistered.builder.js.map +1 -0
  23. package/build/features/ActionExecuter.js.map +1 -1
  24. package/build/features/FeatureInstaller.d.ts +1 -1
  25. package/build/features/FeatureInstallerFactory.js +3 -0
  26. package/build/features/FeatureInstallerFactory.js.map +1 -1
  27. package/build/features/agent/AgentFeature.d.ts +22 -0
  28. package/build/features/agent/AgentFeature.js +24 -0
  29. package/build/features/agent/AgentFeature.js.map +1 -0
  30. package/build/features/agent/actions/RegisterAction.d.ts +54 -0
  31. package/build/features/agent/actions/RegisterAction.js +76 -0
  32. package/build/features/agent/actions/RegisterAction.js.map +1 -0
  33. package/build/features/agent/stores/AgentStore.d.ts +5 -0
  34. package/build/features/agent/stores/AgentStore.js +18 -0
  35. package/build/features/agent/stores/AgentStore.js.map +1 -0
  36. package/build/features/agent/writers/AgentWriter.d.ts +8 -0
  37. package/build/features/agent/writers/AgentWriter.js +31 -0
  38. package/build/features/agent/writers/AgentWriter.js.map +1 -0
  39. package/build/features/event/EventFeature.js +1 -0
  40. package/build/features/event/EventFeature.js.map +1 -1
  41. package/build/stores/StoreFactory.d.ts +2 -0
  42. package/build/stores/StoreFactory.js +2 -0
  43. package/build/stores/StoreFactory.js.map +1 -1
  44. package/build/tests/buildTestCache.js +7 -1
  45. package/build/tests/buildTestCache.js.map +1 -1
  46. package/build/tests/utilities/test.utility.js +3 -3
  47. package/build/writers/WriterFactory.d.ts +2 -0
  48. package/build/writers/WriterFactory.js +2 -0
  49. package/build/writers/WriterFactory.js.map +1 -1
  50. package/package.json +24 -24
  51. package/src/.spruce/errors/errors.types.ts +40 -9
  52. package/src/.spruce/errors/options.types.ts +4 -1
  53. package/src/.spruce/errors/spruceCli/agentAlreadyRegistered.schema.ts +24 -0
  54. package/src/__tests__/behavioral/agents/RegisteringAnAgentAtBoot.test.ts +99 -0
  55. package/src/__tests__/behavioral/onboard/StartingOnboarding.test.ts +2 -7
  56. package/src/__tests__/behavioral/{SettingRemote.test.ts → remote/SettingRemote.test.ts} +3 -3
  57. package/src/__tests__/behavioral/remote/SettingRemoteDoesNotAskTwice.test.ts +68 -0
  58. package/src/errors/SpruceError.ts +4 -0
  59. package/src/errors/agentAlreadyRegistered.builder.ts +14 -0
  60. package/src/features/ActionExecuter.ts +5 -4
  61. package/src/features/FeatureInstallerFactory.ts +3 -0
  62. package/src/features/agent/AgentFeature.ts +31 -0
  63. package/src/features/agent/actions/RegisterAction.ts +79 -0
  64. package/src/features/agent/stores/AgentStore.ts +16 -0
  65. package/src/features/agent/writers/AgentWriter.ts +54 -0
  66. package/src/features/event/EventFeature.ts +1 -0
  67. package/src/stores/StoreFactory.ts +3 -0
  68. package/src/tests/buildTestCache.ts +9 -2
  69. package/src/tests/utilities/test.utility.ts +3 -3
  70. package/src/writers/WriterFactory.ts +3 -0
  71. package/build/__tests__/behavioral/SettingRemote.test.js.map +0 -1
@@ -0,0 +1,99 @@
1
+ import { assert, generateId, test } from '@sprucelabs/test-utils'
2
+ import AgentStore from '../../../features/agent/stores/AgentStore'
3
+ import { SkillStore } from '../../../features/skill/stores/SkillStore'
4
+ import AbstractSkillTest from '../../../tests/AbstractSkillTest'
5
+
6
+ export default class RegisteringAnAgentAtBootTest extends AbstractSkillTest {
7
+ protected static skillCacheKey = 'events'
8
+ private static agentName = generateId()
9
+ private static agents: AgentStore
10
+ private static skills: SkillStore
11
+
12
+ protected static async beforeEach() {
13
+ await super.beforeEach()
14
+ this.agents = this.Store('agent')
15
+ this.skills = this.Store('skill')
16
+ }
17
+
18
+ @test()
19
+ protected static async canCreateRegisteringAnAgentAtBoot() {
20
+ const results = await this.register()
21
+
22
+ const expectedPlugin = this.resolvePath(
23
+ 'src',
24
+ '.spruce',
25
+ 'features',
26
+ 'agent.plugin.ts'
27
+ )
28
+
29
+ const expectedPrompt = this.resolvePath('agents/SYSTEM_PROMPT.md')
30
+ assert.isEqualDeep(results.files, [
31
+ {
32
+ path: expectedPlugin,
33
+ name: 'agent.plugin.ts',
34
+ action: 'generated',
35
+ description: 'Supports your skill with registering ai agents.',
36
+ },
37
+ {
38
+ path: expectedPrompt,
39
+ name: 'SYSTEM_PROMPT.md',
40
+ action: 'generated',
41
+ description: `The prompt file that defines how your AI Platform Agent behaves.`,
42
+ },
43
+ ])
44
+ }
45
+
46
+ @test()
47
+ protected static async bootingRegistersTheAgent() {
48
+ await this.loginAndRegisterSkill()
49
+ await this.boot()
50
+
51
+ const agent = await this.getPlatformAgent()
52
+
53
+ assert.isTruthy(agent, 'Did not register an agent at boot.')
54
+ assert.isEqual(
55
+ agent.name,
56
+ this.agentName,
57
+ 'Did not set name correctly.'
58
+ )
59
+ }
60
+
61
+ @test()
62
+ protected static async returnsAnErrorIfAlreadyRegistered() {
63
+ const results = await this.register()
64
+ assert.isFalsy(results.files, 'Should not have created files.')
65
+ assert.isTruthy(results.errors, 'Should have errors.')
66
+ }
67
+
68
+ private static async register() {
69
+ return await this.Action('agent', 'register', {
70
+ shouldAutoHandleDependencies: true,
71
+ }).execute({
72
+ type: 'system',
73
+ name: this.agentName,
74
+ })
75
+ }
76
+
77
+ private static async loginAndRegisterSkill() {
78
+ await this.people.loginAsDemoPerson()
79
+ await this.skills.register({
80
+ name: 'Agent skill',
81
+ })
82
+ }
83
+
84
+ private static async boot() {
85
+ await this.Action('skill', 'boot').execute({
86
+ local: true,
87
+ onData: (data: string) => {
88
+ this.log(`Boot Log: ${data}`)
89
+ },
90
+ onError: (data: string) => {
91
+ this.log(`Boot Error: ${data}`)
92
+ },
93
+ })
94
+ }
95
+
96
+ private static async getPlatformAgent() {
97
+ return await this.agents.getPlatformAgent()
98
+ }
99
+ }
@@ -39,23 +39,18 @@ export default class StartingOnboardingTest extends AbstractCliTest {
39
39
 
40
40
  // get through first onboarding script and select short onboarding
41
41
  await this.waitForInput()
42
- debugger
43
42
 
44
43
  await this.ui.sendInput('\n')
45
- debugger
44
+
46
45
  await this.waitForInput()
47
- debugger
48
46
 
49
47
  await this.ui.sendInput('immersive')
50
- debugger
48
+
51
49
  await this.waitForInput()
52
- debugger
53
50
 
54
51
  await this.ui.sendInput('\n')
55
- debugger
56
52
 
57
53
  await onboardPromise
58
- debugger
59
54
 
60
55
  const onboardingStore = this.Store('onboarding')
61
56
  assert.isEqual(onboardingStore.getMode(), 'immersive')
@@ -5,9 +5,9 @@ import {
5
5
  REMOTE_SANDBOX,
6
6
  } from '@sprucelabs/spruce-event-utils'
7
7
  import { test, assert } from '@sprucelabs/test-utils'
8
- import { FeatureCode } from '../../features/features.types'
9
- import TerminalInterface from '../../interfaces/TerminalInterface'
10
- import AbstractSkillTest from '../../tests/AbstractSkillTest'
8
+ import { FeatureCode } from '../../../features/features.types'
9
+ import TerminalInterface from '../../../interfaces/TerminalInterface'
10
+ import AbstractSkillTest from '../../../tests/AbstractSkillTest'
11
11
 
12
12
  export default class SettingRemoteTest extends AbstractSkillTest {
13
13
  protected static skillCacheKey = 'events'
@@ -0,0 +1,68 @@
1
+ import { Remote } from '@sprucelabs/spruce-event-utils'
2
+ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
3
+ import { test } from '@sprucelabs/test-utils'
4
+ import RemoteService from '../../../features/event/services/RemoteService'
5
+ import ServiceFactory from '../../../services/ServiceFactory'
6
+ import AbstractSkillTest from '../../../tests/AbstractSkillTest'
7
+
8
+ export default class SettingRemoteDoesNotAskTwiceTest extends AbstractSkillTest {
9
+ protected static skillCacheKey = 'tests'
10
+ @test()
11
+ protected static async canSetRemoteWithoutOneAndOnlyBeAskedOnce() {
12
+ ServiceFactory.setServiceClass('remote', CountingRemoteService)
13
+
14
+ this.cleanEnv()
15
+
16
+ const promise = this.Action('event', 'setRemote', {
17
+ shouldAutoHandleDependencies: true,
18
+ }).execute({})
19
+
20
+ await this.confirmInstallSchemaFeature()
21
+ await this.confirmInstallPermissionFeature()
22
+
23
+ await this.confirmFinishedInstallingDependencies()
24
+ await this.waitForInput()
25
+
26
+ await this.ui.sendInput('local')
27
+
28
+ await promise
29
+ }
30
+
31
+ private static async confirmFinishedInstallingDependencies() {
32
+ await this.waitForInput()
33
+ await this.pressEnter()
34
+ }
35
+
36
+ private static async confirmInstallPermissionFeature() {
37
+ await this.waitForInput()
38
+ await this.pressEnter()
39
+ }
40
+
41
+ private static async confirmInstallSchemaFeature() {
42
+ await this.waitForInput()
43
+ await this.pressEnter()
44
+ }
45
+
46
+ private static async pressEnter() {
47
+ await this.ui.sendInput('\n')
48
+ }
49
+
50
+ private static cleanEnv() {
51
+ const envPath = this.resolvePath('.env')
52
+ diskUtil.deleteFile(envPath)
53
+ diskUtil.writeFile(envPath, 'SKILL_NAME="don\'t double me"')
54
+ }
55
+ }
56
+
57
+ class CountingRemoteService extends RemoteService {
58
+ public static wasCalled = false
59
+ public set(host: Remote) {
60
+ if (CountingRemoteService.wasCalled) {
61
+ throw new Error('Called twice')
62
+ }
63
+
64
+ super.set(host)
65
+
66
+ CountingRemoteService.wasCalled = true
67
+ }
68
+ }
@@ -277,6 +277,10 @@ export default class SpruceError extends AbstractSpruceError<ErrorOptions> {
277
277
  message = `You already have an AppController! Run \`spruce sync.views\` if you are having issues.`
278
278
  break
279
279
 
280
+ case 'AGENT_ALREADY_REGISTERED':
281
+ message = `You already registerd an AI Agent at ${options.promptPath}. If you want to register a new one, delete that file first.`
282
+ break
283
+
280
284
  default:
281
285
  message = super.friendlyMessage()
282
286
  }
@@ -0,0 +1,14 @@
1
+ import { buildErrorSchema } from '@sprucelabs/schema'
2
+
3
+ export default buildErrorSchema({
4
+ id: 'agentAlreadyRegistered',
5
+ name: 'agent already registered',
6
+ fields: {
7
+ promptPath: {
8
+ type: 'text',
9
+ isRequired: true,
10
+ label: 'Prompt Path',
11
+ hint: 'The path to the existing agent prompt file.',
12
+ },
13
+ },
14
+ })
@@ -1,3 +1,4 @@
1
+ import { Schema } from '@sprucelabs/schema'
1
2
  import { eventResponseUtil } from '@sprucelabs/spruce-event-utils'
2
3
  import merge from 'lodash/merge'
3
4
  import SpruceError from '../errors/SpruceError'
@@ -40,8 +41,8 @@ export default class ActionExecuter {
40
41
  private async execute(options: {
41
42
  featureCode: FeatureCode
42
43
  actionCode: string
43
- action: any
44
- originalExecute: any
44
+ action: FeatureAction<Schema>
45
+ originalExecute: FeatureAction<Schema>['execute']
45
46
  options?: Record<string, any>
46
47
  }): Promise<FeatureInstallResponse & FeatureActionResponse> {
47
48
  const {
@@ -187,7 +188,7 @@ export default class ActionExecuter {
187
188
 
188
189
  const originalExecute = action.execute.bind(action)
189
190
 
190
- action.execute = async (options: any) => {
191
+ action.execute = async (options: Record<string, any>) => {
191
192
  return this.execute({
192
193
  featureCode,
193
194
  actionCode,
@@ -197,7 +198,7 @@ export default class ActionExecuter {
197
198
  })
198
199
  }
199
200
 
200
- return action as any
201
+ return action as FeatureAction<Schema>
201
202
  }
202
203
  }
203
204
 
@@ -6,6 +6,7 @@ import { ApiClientFactory } from '../types/apiClient.types'
6
6
  import { GraphicsInterface } from '../types/cli.types'
7
7
  import { FeatureOptions } from './AbstractFeature'
8
8
  import ActionExecuter from './ActionExecuter'
9
+ import AgentFeature from './agent/AgentFeature'
9
10
  import CacheFeature from './cache/CacheFeature'
10
11
  import ConversationFeature from './conversation/ConversationFeature'
11
12
  import DependencyFeature from './dependencies/DependencyFeature'
@@ -55,6 +56,7 @@ export default class FeatureInstallerFactory {
55
56
  DependencyFeature,
56
57
  PolishFeature,
57
58
  PermissionFeature,
59
+ AgentFeature,
58
60
  ]
59
61
 
60
62
  public static readonly featureCodes: FeatureCode[] = [
@@ -80,6 +82,7 @@ export default class FeatureInstallerFactory {
80
82
  'dependency',
81
83
  'polish',
82
84
  'permission',
85
+ 'agent',
83
86
  ]
84
87
 
85
88
  public static WithAllFeatures(
@@ -0,0 +1,31 @@
1
+ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
2
+ import { FileDescription } from '../../types/cli.types'
3
+ import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
4
+ import { FeatureCode } from '../features.types'
5
+
6
+ export default class AgentFeature extends AbstractFeature {
7
+ public description = 'AI Agent support for your skill.'
8
+ public code: FeatureCode = 'agent'
9
+ public nameReadable = 'Agent'
10
+ public actionsDir = diskUtil.resolvePath(__dirname, 'actions')
11
+ public dependencies: FeatureDependency[] = [
12
+ { code: 'event', isRequired: true },
13
+ ]
14
+ public packageDependencies = [
15
+ {
16
+ name: '@sprucelabs/spruce-agent-plugin',
17
+ },
18
+ ]
19
+
20
+ public readonly fileDescriptions: FileDescription[] = []
21
+ }
22
+
23
+ declare module '../../features/features.types' {
24
+ interface FeatureMap {
25
+ agent: AgentFeature
26
+ }
27
+
28
+ interface FeatureOptionsMap {
29
+ agent: undefined
30
+ }
31
+ }
@@ -0,0 +1,79 @@
1
+ import { buildSchema, SchemaValues } from '@sprucelabs/schema'
2
+ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
3
+ import SpruceError from '../../../errors/SpruceError'
4
+ import AbstractAction from '../../AbstractAction'
5
+ import { FeatureActionResponse } from '../../features.types'
6
+
7
+ const optionsSchema = buildSchema({
8
+ id: 'registerAgentOptions',
9
+ description:
10
+ 'Turn Sprucebot into an agent of your own design. Heck, even give him a new name! You can create a Platform Agent or a Skill Agent. Skill Agent coming soon...',
11
+ fields: {
12
+ type: {
13
+ label: 'Agent Type',
14
+ type: 'select',
15
+ hint: 'You can only create a System Agent if you have permission to do so...',
16
+ options: {
17
+ choices: [
18
+ {
19
+ value: 'system',
20
+ label: 'System Agent',
21
+ },
22
+ {
23
+ value: 'skill',
24
+ label: 'Skill Agent (coming soon)',
25
+ },
26
+ ],
27
+ },
28
+ },
29
+ name: {
30
+ type: 'text',
31
+ label: 'Agent Name',
32
+ isRequired: true,
33
+ },
34
+ },
35
+ })
36
+
37
+ type OptionsSchema = typeof optionsSchema
38
+ type Options = SchemaValues<OptionsSchema>
39
+
40
+ export default class RegisterAction extends AbstractAction<OptionsSchema> {
41
+ public optionsSchema = optionsSchema
42
+ public invocationMessage = 'Registering your AI Agent... 🤖'
43
+
44
+ public async execute(options: Options): Promise<FeatureActionResponse> {
45
+ const { name } = this.validateAndNormalizeOptions(options)
46
+
47
+ const writer = this.Writer('agent')
48
+ const promptPath = writer.resolveSystemPromptPath(this.cwd)
49
+ if (diskUtil.doesFileExist(promptPath)) {
50
+ return {
51
+ errors: [
52
+ new SpruceError({
53
+ code: 'AGENT_ALREADY_REGISTERED',
54
+ promptPath,
55
+ }),
56
+ ],
57
+ }
58
+ }
59
+ const plugin = await writer.writePlugin(this.cwd)
60
+ const prompt = await writer.writeSystemPrompt(this.cwd, {
61
+ name,
62
+ })
63
+
64
+ return {
65
+ headline: `AI Agent ${name} Registered Successfully!`,
66
+ summaryLines: [
67
+ `Registered ${name} AI Agent!`,
68
+ `Agent name: ${name}`,
69
+ ],
70
+ hints: [
71
+ 'Next steps:',
72
+ ' - Customize your agent prompt in agents/SYSTEM_PROMPT.md',
73
+ ' - Boot your skill',
74
+ ' - Message the agent (try responding to the pin code email/text)',
75
+ ],
76
+ files: [...plugin, ...prompt],
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,16 @@
1
+ import AbstractStore from '../../../stores/AbstractStore'
2
+
3
+ export default class AgentStore extends AbstractStore {
4
+ public name = 'agent'
5
+
6
+ public async getPlatformAgent() {
7
+ const client = await this.connectToApi({
8
+ shouldAuthAsCurrentSkill: true,
9
+ })
10
+ const [{ agent }] = await client.emitAndFlattenResponses(
11
+ 'get-agent::v2020_12_25'
12
+ )
13
+
14
+ return agent
15
+ }
16
+ }
@@ -0,0 +1,54 @@
1
+ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
2
+ import AbstractWriter from '../../../writers/AbstractWriter'
3
+
4
+ export default class AgentWriter extends AbstractWriter {
5
+ public async writePlugin(cwd: string) {
6
+ const destination = diskUtil.resolveHashSprucePath(
7
+ cwd,
8
+ 'features',
9
+ 'agent.plugin.ts'
10
+ )
11
+
12
+ const pluginContents = this.templates.agentPlugin()
13
+
14
+ const results = await this.writeFileIfChangedMixinResults(
15
+ destination,
16
+ pluginContents,
17
+ 'Supports your skill with registering ai agents.'
18
+ )
19
+
20
+ return results
21
+ }
22
+
23
+ public async writeSystemPrompt(
24
+ destinationDir: string,
25
+ options: {
26
+ name: string
27
+ }
28
+ ) {
29
+ const { name } = options
30
+
31
+ const destination = this.resolveSystemPromptPath(destinationDir)
32
+ const promptContents = this.templates.agentSystemPrompt({
33
+ name,
34
+ })
35
+
36
+ const results = await this.writeFileIfChangedMixinResults(
37
+ destination,
38
+ promptContents,
39
+ `The prompt file that defines how your AI Platform Agent behaves.`
40
+ )
41
+
42
+ return results
43
+ }
44
+
45
+ public resolveSystemPromptPath(destinationDir: string) {
46
+ const filename = 'SYSTEM_PROMPT.md'
47
+ const destination = diskUtil.resolvePath(
48
+ destinationDir,
49
+ 'agents',
50
+ filename
51
+ )
52
+ return destination
53
+ }
54
+ }
@@ -104,6 +104,7 @@ export default class EventFeature extends AbstractFeature {
104
104
  (featureCode === 'event' ||
105
105
  featureCode === 'eventContract' ||
106
106
  actionCode === 'login') &&
107
+ this.initiatingAction !== 'event.setRemote' &&
107
108
  actionCode !== 'setRemote'
108
109
 
109
110
  if (isRemoteRelevant) {
@@ -1,3 +1,4 @@
1
+ import AgentStore from '../features/agent/stores/AgentStore'
1
2
  import ConversationStore from '../features/conversation/stores/ConversationStore'
2
3
  import EventStore from '../features/event/stores/EventStore'
3
4
  import ListenerStore from '../features/event/stores/ListenerStore'
@@ -78,6 +79,7 @@ export interface StoreMap {
78
79
  view: ViewStore
79
80
  listener: ListenerStore
80
81
  permission: PermissionStore
82
+ agent: AgentStore
81
83
  }
82
84
 
83
85
  const storeMap = {
@@ -91,6 +93,7 @@ const storeMap = {
91
93
  view: ViewStore,
92
94
  listener: ListenerStore,
93
95
  permission: PermissionStore,
96
+ agent: AgentStore,
94
97
  }
95
98
 
96
99
  export type StoreCode = keyof StoreMap
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { execSync } from 'child_process'
3
- import { diskUtil } from '@sprucelabs/spruce-skill-utils'
3
+ import { RemoteService } from '@sprucelabs/spruce-event-utils'
4
+ import { diskUtil, EnvService } from '@sprucelabs/spruce-skill-utils'
4
5
  import dotenv from 'dotenv'
5
6
  import TerminalInterface from '../interfaces/TerminalInterface'
6
7
  import ImportService from '../services/ImportService'
@@ -206,11 +207,17 @@ async function run() {
206
207
  diskUtil.deleteDir(cwd)
207
208
  }
208
209
 
209
- renderLine(lineNum, `Starting to build '${cacheKey}'...`, [
210
+ renderLine(lineNum, `Building '${cacheKey}'...`, [
210
211
  GraphicsTextEffect.Green,
211
212
  ])
212
213
 
213
214
  try {
215
+ const env = new EnvService(cwd)
216
+ const remote = new RemoteService(env)
217
+ if (!remote.getHost()) {
218
+ remote.set('local')
219
+ }
220
+
214
221
  await fixture.installFeatures(options, cacheKey)
215
222
  renderLine(
216
223
  lineNum,
@@ -89,9 +89,9 @@ const testUtil = {
89
89
  name: string | RegExp,
90
90
  files: GeneratedFile[] | undefined
91
91
  ): string {
92
- const file = (files ?? []).find((f) => f.name.search(name) > -1)?.path
92
+ const path = (files ?? []).find((f) => f.name.search(name) > -1)?.path
93
93
  assert.isTruthy(
94
- file,
94
+ path,
95
95
  `file named '${name}' not found in generated files.\n\n${JSON.stringify(
96
96
  files ?? [],
97
97
  null,
@@ -99,7 +99,7 @@ const testUtil = {
99
99
  )}`
100
100
  )
101
101
 
102
- return file
102
+ return path
103
103
  },
104
104
 
105
105
  assertFileByPathInGeneratedFiles(
@@ -1,5 +1,6 @@
1
1
  import { SettingsService } from '@sprucelabs/spruce-skill-utils'
2
2
  import { Templates } from '@sprucelabs/spruce-templates'
3
+ import AgentWriter from '../features/agent/writers/AgentWriter'
3
4
  import ConversationWriter from '../features/conversation/writers/ConversationWriter'
4
5
  import DeployWriter from '../features/deploy/writers/DeployWriter'
5
6
  import ErrorWriter from '../features/error/writers/ErrorWriter'
@@ -26,6 +27,7 @@ const classMap = {
26
27
  schema: SchemaWriter,
27
28
  skill: SkillGenerator,
28
29
  test: TestWriter,
30
+ agent: AgentWriter,
29
31
  node: NodeWriter,
30
32
  vscode: VsCodeWriter,
31
33
  conversation: ConversationWriter,
@@ -102,6 +104,7 @@ export interface WriterMap {
102
104
  log: LogWriter
103
105
  polish: PolishWriter
104
106
  permission: PermissionWriter
107
+ agent: AgentWriter
105
108
  }
106
109
 
107
110
  export type WriterCode = keyof WriterMap
@@ -1 +0,0 @@
1
- {"version":3,"file":"SettingRemote.test.js","sourceRoot":"","sources":["../../../src/__tests__/behavioral/SettingRemote.test.ts"],"names":[],"mappings":"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"}