@ai-outfitter/outfitter 0.3.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.
- package/LICENSE.md +58 -0
- package/README.md +256 -0
- package/dist/agents/AdapterProfileControls.d.ts +20 -0
- package/dist/agents/AdapterProfileControls.js +63 -0
- package/dist/agents/AdapterProfileControls.js.map +1 -0
- package/dist/agents/AdapterStatePaths.d.ts +12 -0
- package/dist/agents/AdapterStatePaths.js +44 -0
- package/dist/agents/AdapterStatePaths.js.map +1 -0
- package/dist/agents/AgentAdapter.d.ts +32 -0
- package/dist/agents/AgentAdapter.js +2 -0
- package/dist/agents/AgentAdapter.js.map +1 -0
- package/dist/agents/AgentRegistry.d.ts +6 -0
- package/dist/agents/AgentRegistry.js +17 -0
- package/dist/agents/AgentRegistry.js.map +1 -0
- package/dist/agents/LaunchResources.d.ts +13 -0
- package/dist/agents/LaunchResources.js +35 -0
- package/dist/agents/LaunchResources.js.map +1 -0
- package/dist/agents/ResourceIdentity.d.ts +2 -0
- package/dist/agents/ResourceIdentity.js +51 -0
- package/dist/agents/ResourceIdentity.js.map +1 -0
- package/dist/agents/claude/ClaudeAdapter.d.ts +2 -0
- package/dist/agents/claude/ClaudeAdapter.js +117 -0
- package/dist/agents/claude/ClaudeAdapter.js.map +1 -0
- package/dist/agents/claude/ClaudeCompositeProfileWriter.d.ts +5 -0
- package/dist/agents/claude/ClaudeCompositeProfileWriter.js +7 -0
- package/dist/agents/claude/ClaudeCompositeProfileWriter.js.map +1 -0
- package/dist/agents/pi/PiAdapter.d.ts +2 -0
- package/dist/agents/pi/PiAdapter.js +229 -0
- package/dist/agents/pi/PiAdapter.js.map +1 -0
- package/dist/agents/pi/PiCompositeProfileWriter.d.ts +5 -0
- package/dist/agents/pi/PiCompositeProfileWriter.js +7 -0
- package/dist/agents/pi/PiCompositeProfileWriter.js.map +1 -0
- package/dist/agents/pi/PiMcpConfig.d.ts +2 -0
- package/dist/agents/pi/PiMcpConfig.js +114 -0
- package/dist/agents/pi/PiMcpConfig.js.map +1 -0
- package/dist/agents/pi/PiSettingsMergePolicy.d.ts +17 -0
- package/dist/agents/pi/PiSettingsMergePolicy.js +59 -0
- package/dist/agents/pi/PiSettingsMergePolicy.js.map +1 -0
- package/dist/cli/OutfitterCli.d.ts +4 -0
- package/dist/cli/OutfitterCli.js +32 -0
- package/dist/cli/OutfitterCli.js.map +1 -0
- package/dist/cli/commands/CommandObject.d.ts +11 -0
- package/dist/cli/commands/CommandObject.js +5 -0
- package/dist/cli/commands/CommandObject.js.map +1 -0
- package/dist/cli/commands/FirstRunWelcomeProfile.d.ts +11 -0
- package/dist/cli/commands/FirstRunWelcomeProfile.js +107 -0
- package/dist/cli/commands/FirstRunWelcomeProfile.js.map +1 -0
- package/dist/cli/commands/PiLoginLaunch.d.ts +10 -0
- package/dist/cli/commands/PiLoginLaunch.js +76 -0
- package/dist/cli/commands/PiLoginLaunch.js.map +1 -0
- package/dist/cli/commands/RunCommand.d.ts +30 -0
- package/dist/cli/commands/RunCommand.js +299 -0
- package/dist/cli/commands/RunCommand.js.map +1 -0
- package/dist/cli/commands/SetupCommand.d.ts +34 -0
- package/dist/cli/commands/SetupCommand.js +379 -0
- package/dist/cli/commands/SetupCommand.js.map +1 -0
- package/dist/cli/commands/SyncCommand.d.ts +28 -0
- package/dist/cli/commands/SyncCommand.js +178 -0
- package/dist/cli/commands/SyncCommand.js.map +1 -0
- package/dist/cli/commands/WelcomeCommand.d.ts +54 -0
- package/dist/cli/commands/WelcomeCommand.js +214 -0
- package/dist/cli/commands/WelcomeCommand.js.map +1 -0
- package/dist/cli/commands/profile/Command.d.ts +6 -0
- package/dist/cli/commands/profile/Command.js +21 -0
- package/dist/cli/commands/profile/Command.js.map +1 -0
- package/dist/cli/commands/profile/CreateCommand.d.ts +19 -0
- package/dist/cli/commands/profile/CreateCommand.js +115 -0
- package/dist/cli/commands/profile/CreateCommand.js.map +1 -0
- package/dist/cli/commands/profile/ListCommand.d.ts +17 -0
- package/dist/cli/commands/profile/ListCommand.js +85 -0
- package/dist/cli/commands/profile/ListCommand.js.map +1 -0
- package/dist/cli/commands/profile/Shared.d.ts +9 -0
- package/dist/cli/commands/profile/Shared.js +10 -0
- package/dist/cli/commands/profile/Shared.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +22 -0
- package/dist/cli.js.map +1 -0
- package/dist/compositeProfile/CompositeProfile.d.ts +8 -0
- package/dist/compositeProfile/CompositeProfile.js +6 -0
- package/dist/compositeProfile/CompositeProfile.js.map +1 -0
- package/dist/compositeProfile/CompositeProfileAssembler.d.ts +12 -0
- package/dist/compositeProfile/CompositeProfileAssembler.js +32 -0
- package/dist/compositeProfile/CompositeProfileAssembler.js.map +1 -0
- package/dist/compositeProfile/CompositeProfileFile.d.ts +16 -0
- package/dist/compositeProfile/CompositeProfileFile.js +16 -0
- package/dist/compositeProfile/CompositeProfileFile.js.map +1 -0
- package/dist/compositeProfile/CompositeProfileTemplate.d.ts +15 -0
- package/dist/compositeProfile/CompositeProfileTemplate.js +65 -0
- package/dist/compositeProfile/CompositeProfileTemplate.js.map +1 -0
- package/dist/compositeProfile/CompositeProfileWatcher.d.ts +18 -0
- package/dist/compositeProfile/CompositeProfileWatcher.js +46 -0
- package/dist/compositeProfile/CompositeProfileWatcher.js.map +1 -0
- package/dist/compositeProfile/StatePersistence.d.ts +24 -0
- package/dist/compositeProfile/StatePersistence.js +224 -0
- package/dist/compositeProfile/StatePersistence.js.map +1 -0
- package/dist/merge/ArrayMergePolicy.d.ts +8 -0
- package/dist/merge/ArrayMergePolicy.js +45 -0
- package/dist/merge/ArrayMergePolicy.js.map +1 -0
- package/dist/merge/SettingsValueMerger.d.ts +11 -0
- package/dist/merge/SettingsValueMerger.js +34 -0
- package/dist/merge/SettingsValueMerger.js.map +1 -0
- package/dist/profiles/Profile.d.ts +32 -0
- package/dist/profiles/Profile.js +7 -0
- package/dist/profiles/Profile.js.map +1 -0
- package/dist/profiles/ProfileCache.d.ts +8 -0
- package/dist/profiles/ProfileCache.js +36 -0
- package/dist/profiles/ProfileCache.js.map +1 -0
- package/dist/profiles/ProfileLoader.d.ts +24 -0
- package/dist/profiles/ProfileLoader.js +169 -0
- package/dist/profiles/ProfileLoader.js.map +1 -0
- package/dist/profiles/ProfileMerger.d.ts +20 -0
- package/dist/profiles/ProfileMerger.js +97 -0
- package/dist/profiles/ProfileMerger.js.map +1 -0
- package/dist/profiles/ProfileSource.d.ts +35 -0
- package/dist/profiles/ProfileSource.js +13 -0
- package/dist/profiles/ProfileSource.js.map +1 -0
- package/dist/schemas/profile-source.schema.json +29 -0
- package/dist/schemas/profile.schema.json +115 -0
- package/dist/schemas/settings.schema.json +37 -0
- package/dist/settings/Settings.d.ts +17 -0
- package/dist/settings/Settings.js +5 -0
- package/dist/settings/Settings.js.map +1 -0
- package/dist/settings/SettingsLoader.d.ts +33 -0
- package/dist/settings/SettingsLoader.js +129 -0
- package/dist/settings/SettingsLoader.js.map +1 -0
- package/dist/settings/SettingsMerger.d.ts +2 -0
- package/dist/settings/SettingsMerger.js +31 -0
- package/dist/settings/SettingsMerger.js.map +1 -0
- package/dist/validation/SchemaValidator.d.ts +11 -0
- package/dist/validation/SchemaValidator.js +36 -0
- package/dist/validation/SchemaValidator.js.map +1 -0
- package/dist/validation/YamlDocument.d.ts +13 -0
- package/dist/validation/YamlDocument.js +11 -0
- package/dist/validation/YamlDocument.js.map +1 -0
- package/doc/.deepreview +30 -0
- package/doc/architecture.md +834 -0
- package/doc/controllable-elements.md +162 -0
- package/doc/file_structure.md +133 -0
- package/doc/integration_test_system.md +214 -0
- package/doc/specs/validating_requirements_with_rules.md +55 -0
- package/doc/state_writeback_strategy.md +334 -0
- package/package.json +73 -0
- package/requirements/OFTR-001-project-foundation.md +53 -0
- package/requirements/OFTR-002-settings.md +65 -0
- package/requirements/OFTR-003-profiles.md +51 -0
- package/requirements/OFTR-004-sync-and-setup.md +57 -0
- package/requirements/OFTR-005-run-and-composite-profile.md +60 -0
- package/requirements/OFTR-006-agent-adapters.md +64 -0
- package/requirements/OFTR-007-controllable-elements.md +32 -0
- package/requirements/OFTR-008-requirements-governance.md +42 -0
- package/requirements/OFTR-009-release-publishing.md +25 -0
- package/requirements/OFTR-010-onboarding-welcome.md +38 -0
- package/src/schemas/SchemaDocument.ts +20 -0
- package/src/schemas/profile-source.schema.json +29 -0
- package/src/schemas/profile.schema.json +115 -0
- package/src/schemas/settings.schema.json +37 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { normalizeExtensionResourceIdentity, normalizeLaunchResourceIdentity } from '../ResourceIdentity.js';
|
|
2
|
+
export const piSettingsArrayPolicies = {
|
|
3
|
+
packages: {
|
|
4
|
+
mode: 'uniqueBy',
|
|
5
|
+
order: 'append',
|
|
6
|
+
winner: 'last',
|
|
7
|
+
key: (entry) => normalizePiSettingsPackageResourceIdentity(entry) ?? createUnknownPiSettingsArrayKey(entry),
|
|
8
|
+
},
|
|
9
|
+
extensions: createStringResourceArrayPolicy(normalizeExtensionResourceIdentity),
|
|
10
|
+
skills: createStringResourceArrayPolicy(normalizeLaunchResourceIdentity),
|
|
11
|
+
prompts: createStringResourceArrayPolicy(normalizeLaunchResourceIdentity),
|
|
12
|
+
themes: createStringResourceArrayPolicy(normalizeLaunchResourceIdentity),
|
|
13
|
+
};
|
|
14
|
+
export const filterPiSettingsPackagesDuplicatingExtensions = (packages, extensionSources) => {
|
|
15
|
+
const extensionIdentities = new Set(extensionSources.map(normalizeExtensionResourceIdentity));
|
|
16
|
+
if (extensionIdentities.size === 0) {
|
|
17
|
+
return packages;
|
|
18
|
+
}
|
|
19
|
+
return packages.filter((entry) => {
|
|
20
|
+
const identity = normalizePiSettingsPackageResourceIdentity(entry);
|
|
21
|
+
return identity === undefined || !extensionIdentities.has(identity);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
export const normalizePiSettingsPackageResourceIdentity = (entry) => {
|
|
25
|
+
const source = readPiSettingsPackageSource(entry);
|
|
26
|
+
return source === undefined ? undefined : normalizeExtensionResourceIdentity(source);
|
|
27
|
+
};
|
|
28
|
+
export const readPiSettingsPackageSource = (entry) => {
|
|
29
|
+
if (typeof entry === 'string') {
|
|
30
|
+
return entry;
|
|
31
|
+
}
|
|
32
|
+
if (entry === null || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const record = entry;
|
|
36
|
+
return typeof record.source === 'string' ? record.source : undefined;
|
|
37
|
+
};
|
|
38
|
+
function createStringResourceArrayPolicy(normalize) {
|
|
39
|
+
return {
|
|
40
|
+
mode: 'uniqueBy',
|
|
41
|
+
order: 'append',
|
|
42
|
+
winner: 'last',
|
|
43
|
+
key: (entry) => (typeof entry === 'string' ? normalize(entry) : createUnknownPiSettingsArrayKey(entry)),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const createUnknownPiSettingsArrayKey = (entry) => `literal:${stableStringify(entry)}`;
|
|
47
|
+
const stableStringify = (value) => {
|
|
48
|
+
if (value === null || typeof value !== 'object') {
|
|
49
|
+
return JSON.stringify(value);
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
return `[${value.map(stableStringify).join(',')}]`;
|
|
53
|
+
}
|
|
54
|
+
return `{${Object.entries(value)
|
|
55
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
56
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
|
|
57
|
+
.join(',')}}`;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=PiSettingsMergePolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PiSettingsMergePolicy.js","sourceRoot":"","sources":["../../../src/agents/pi/PiSettingsMergePolicy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AAI7G,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,CAAC,KAAc,EAAE,EAAE,CACtB,0CAA0C,CAAC,KAAK,CAAC,IAAI,+BAA+B,CAAC,KAAK,CAAC;KAC9F;IACD,UAAU,EAAE,+BAA+B,CAAC,kCAAkC,CAAC;IAC/E,MAAM,EAAE,+BAA+B,CAAC,+BAA+B,CAAC;IACxE,OAAO,EAAE,+BAA+B,CAAC,+BAA+B,CAAC;IACzE,MAAM,EAAE,+BAA+B,CAAC,+BAA+B,CAAC;CACW,CAAC;AAEtF,MAAM,CAAC,MAAM,6CAA6C,GAAG,CAC3D,QAA4B,EAC5B,gBAAmC,EACf,EAAE;IACtB,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAE9F,IAAI,mBAAmB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC/B,MAAM,QAAQ,GAAG,0CAA0C,CAAC,KAAK,CAAC,CAAC;QACnE,OAAO,QAAQ,KAAK,SAAS,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,KAAc,EAAsB,EAAE;IAC/F,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAClD,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kCAAkC,CAAC,MAAM,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,KAAc,EAAsB,EAAE;IAChF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,KAA0C,CAAC;IAC1D,OAAO,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC,CAAC;AAEF,SAAS,+BAA+B,CAAC,SAAqC;IAC5E,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAC;KACxG,CAAC;AACJ,CAAC;AAED,MAAM,+BAA+B,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,WAAW,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;AAExG,MAAM,eAAe,GAAG,CAAC,KAAc,EAAU,EAAE;IACjD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACrD,CAAC;IAED,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,KAA0C,CAAC;SAClE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SACpD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;SACvE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClB,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Assembles the top-level Outfitter Commander program from command objects.
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { createProfileCommands } from './commands/profile/Command.js';
|
|
5
|
+
import { createRunCommand } from './commands/RunCommand.js';
|
|
6
|
+
import { createSetupCommand } from './commands/SetupCommand.js';
|
|
7
|
+
import { createSyncCommand } from './commands/SyncCommand.js';
|
|
8
|
+
import { createWelcomeCommand } from './commands/WelcomeCommand.js';
|
|
9
|
+
export const createDefaultCommands = () => [
|
|
10
|
+
createRunCommand(),
|
|
11
|
+
createSetupCommand(),
|
|
12
|
+
createSyncCommand(),
|
|
13
|
+
createWelcomeCommand(),
|
|
14
|
+
...createProfileCommands(),
|
|
15
|
+
];
|
|
16
|
+
export const createOutfitterProgram = (commands = createDefaultCommands()) => {
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name('outfitter')
|
|
20
|
+
.description('Profile-oriented wrapper for launching pi, Claude Code, and future agent CLIs.')
|
|
21
|
+
.version(readPackageVersion());
|
|
22
|
+
for (const command of commands) {
|
|
23
|
+
command.register(program);
|
|
24
|
+
}
|
|
25
|
+
return program;
|
|
26
|
+
};
|
|
27
|
+
const readPackageVersion = () => {
|
|
28
|
+
const packageJsonPath = new URL('../../package.json', import.meta.url);
|
|
29
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
30
|
+
return packageJson.version;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=OutfitterCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OutfitterCli.js","sourceRoot":"","sources":["../../src/cli/OutfitterCli.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAoB,EAAE,CAAC;IAC1D,gBAAgB,EAAE;IAClB,kBAAkB,EAAE;IACpB,iBAAiB,EAAE;IACnB,oBAAoB,EAAE;IACtB,GAAG,qBAAqB,EAAE;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,WAAqC,qBAAqB,EAAE,EAAW,EAAE;IAC9G,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,WAAW,CAAC;SACjB,WAAW,CAAC,gFAAgF,CAAC;SAC7F,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEjC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,GAAW,EAAE;IACtC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAwB,CAAC;IAE7F,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export interface CommandObject {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly description: string;
|
|
5
|
+
register(program: Command): void;
|
|
6
|
+
}
|
|
7
|
+
export interface CommandDescriptor {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly description: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const describeCommandObject: (command: CommandObject) => CommandDescriptor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandObject.js","sourceRoot":"","sources":["../../../src/cli/commands/CommandObject.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAsB,EAAqB,EAAE,CAAC,CAAC;IACnF,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,WAAW,EAAE,OAAO,CAAC,WAAW;CACjC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WelcomeCommandResult } from './WelcomeCommand.js';
|
|
2
|
+
export interface PersistedFirstRunWelcomeProfile {
|
|
3
|
+
readonly profileId: string;
|
|
4
|
+
readonly createdProfile: boolean;
|
|
5
|
+
readonly messages?: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export interface FirstRunWelcomeProfileOptions {
|
|
8
|
+
readonly sourceProfileDirectory?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const persistFirstRunWelcomeProfile: (homeDirectory: string, settingsPath: string, welcomeResult: WelcomeCommandResult | undefined, options?: FirstRunWelcomeProfileOptions) => PersistedFirstRunWelcomeProfile | undefined;
|
|
11
|
+
export declare const updateSettingsDefaultProfile: (settingsPath: string, profileId: string) => void;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Persists first-run welcome choices as a local profile used before launching Pi.
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { parse, stringify } from 'yaml';
|
|
5
|
+
export const persistFirstRunWelcomeProfile = (homeDirectory, settingsPath, welcomeResult, options = {}) => {
|
|
6
|
+
if (welcomeResult === undefined || !welcomeResult.answered || welcomeResult.selectedRole === undefined) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const welcomeProfile = createFirstRunWelcomeProfile(welcomeResult, welcomeResult.selectedRole);
|
|
10
|
+
const profileDirectory = join(homeDirectory, '.outfitter', 'profiles', welcomeProfile.id);
|
|
11
|
+
const profilePath = join(profileDirectory, 'profile.yml');
|
|
12
|
+
const createdProfile = !existsSync(profilePath);
|
|
13
|
+
const messages = [];
|
|
14
|
+
if (createdProfile) {
|
|
15
|
+
if (options.sourceProfileDirectory !== undefined && existsSync(options.sourceProfileDirectory)) {
|
|
16
|
+
cpSync(options.sourceProfileDirectory, profileDirectory, { recursive: true, force: false });
|
|
17
|
+
updateCopiedProfile(profilePath, welcomeProfile.extensions);
|
|
18
|
+
excludeDefaultProfileSources(settingsPath, welcomeProfile.id);
|
|
19
|
+
messages.push(`Copied the ${welcomeProfile.label} profile locally so your extension choices can be edited at ${profilePath}.`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
mkdirSync(profileDirectory, { recursive: true });
|
|
23
|
+
writeFileSync(profilePath, welcomeProfile.content);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
updateSettingsDefaultProfile(settingsPath, welcomeProfile.id);
|
|
27
|
+
return {
|
|
28
|
+
profileId: welcomeProfile.id,
|
|
29
|
+
createdProfile,
|
|
30
|
+
...(messages.length === 0 ? {} : { messages }),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const createFirstRunWelcomeProfile = (welcomeResult, selectedRole) => {
|
|
34
|
+
const profileId = selectedRole.id;
|
|
35
|
+
const extensions = welcomeResult.selectedLoadout?.selectedItems.map((item) => item.source) ?? [];
|
|
36
|
+
const rolePrompt = firstRunWelcomeRolePrompts[selectedRole.id];
|
|
37
|
+
return {
|
|
38
|
+
id: profileId,
|
|
39
|
+
label: selectedRole.label,
|
|
40
|
+
content: createFirstRunWelcomeProfileContent(profileId, selectedRole.label, rolePrompt, extensions),
|
|
41
|
+
extensions,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const firstRunWelcomeRolePrompts = {
|
|
45
|
+
engineer: 'You are operating as an engineering-focused coding agent.\nPrioritize maintainable implementation, clear tests, concise diffs, and verification evidence.\nBefore changing code, inspect the existing project conventions and reuse established patterns.',
|
|
46
|
+
data_analyst: 'You are operating as a data-analysis-focused agent.\nPrioritize careful data inspection, reproducible analysis steps, clear assumptions, and actionable summaries.\nWhen data or methodology is uncertain, call out limitations and validation checks explicitly.',
|
|
47
|
+
};
|
|
48
|
+
const createFirstRunWelcomeProfileContent = (profileId, roleLabel, rolePrompt, extensions) => {
|
|
49
|
+
const lines = [`id: ${profileId}`, `label: ${roleLabel}`, 'controls:'];
|
|
50
|
+
if (extensions.length > 0) {
|
|
51
|
+
lines.push(' pi:', ' extensions:', ...extensions.map((extension) => ` - ${extension}`));
|
|
52
|
+
}
|
|
53
|
+
lines.push(' append_system_prompt: |', ...rolePrompt.split('\n').map((line) => ` ${line}`), '');
|
|
54
|
+
return lines.join('\n');
|
|
55
|
+
};
|
|
56
|
+
const updateCopiedProfile = (profilePath, extensions) => {
|
|
57
|
+
const profile = readRecord(parse(readFileSync(profilePath, 'utf8')));
|
|
58
|
+
const controls = readRecord(profile.controls);
|
|
59
|
+
const piControls = readRecord(controls.pi);
|
|
60
|
+
controls.extensions = [];
|
|
61
|
+
piControls.extensions = [...extensions];
|
|
62
|
+
controls.pi = piControls;
|
|
63
|
+
profile.controls = controls;
|
|
64
|
+
mkdirSync(dirname(profilePath), { recursive: true });
|
|
65
|
+
writeFileSync(profilePath, stringify(profile));
|
|
66
|
+
};
|
|
67
|
+
const readRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? { ...value } : {};
|
|
68
|
+
const defaultProfilesSourceGithub = 'ai-outfitter/default-profiles';
|
|
69
|
+
const defaultProfilesSourcePath = 'profiles';
|
|
70
|
+
const defaultProfilesSourceUri = 'https://github.com/ai-outfitter/default-profiles';
|
|
71
|
+
const excludeDefaultProfileSources = (settingsPath, profileId) => {
|
|
72
|
+
const document = readRecord(parse(readFileSync(settingsPath, 'utf8')));
|
|
73
|
+
const rawProfileSources = document.profile_sources;
|
|
74
|
+
const profileSources = Array.isArray(rawProfileSources) ? rawProfileSources : [];
|
|
75
|
+
const nextProfileSources = profileSources.map((source) => {
|
|
76
|
+
const record = readRecord(source);
|
|
77
|
+
if (!isDefaultProfilesSource(record)) {
|
|
78
|
+
return source;
|
|
79
|
+
}
|
|
80
|
+
const except = Array.isArray(record.except)
|
|
81
|
+
? record.except.filter((item) => typeof item === 'string')
|
|
82
|
+
: [];
|
|
83
|
+
return { ...record, except: [...new Set([...except, profileId])] };
|
|
84
|
+
});
|
|
85
|
+
writeFileSync(settingsPath, stringify({ ...document, profile_sources: nextProfileSources }));
|
|
86
|
+
};
|
|
87
|
+
const isDefaultProfilesSource = (source) => {
|
|
88
|
+
if (source.path !== defaultProfilesSourcePath) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (source.github === defaultProfilesSourceGithub) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return typeof source.uri === 'string' && normalizeDefaultProfilesSourceUri(source.uri) === defaultProfilesSourceUri;
|
|
95
|
+
};
|
|
96
|
+
const normalizeDefaultProfilesSourceUri = (uri) => uri
|
|
97
|
+
.replace(/^git\+/u, '')
|
|
98
|
+
.replace(/\/$/u, '')
|
|
99
|
+
.replace(/\.git$/u, '');
|
|
100
|
+
export const updateSettingsDefaultProfile = (settingsPath, profileId) => {
|
|
101
|
+
const content = readFileSync(settingsPath, 'utf8');
|
|
102
|
+
const nextContent = /^default_profile:.*$/mu.test(content)
|
|
103
|
+
? content.replace(/^default_profile:.*$/gmu, `default_profile: ${profileId}`)
|
|
104
|
+
: `${content.replace(/\s*$/u, '\n')}default_profile: ${profileId}\n`;
|
|
105
|
+
writeFileSync(settingsPath, nextContent);
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=FirstRunWelcomeProfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirstRunWelcomeProfile.js","sourceRoot":"","sources":["../../../src/cli/commands/FirstRunWelcomeProfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentLaunchPlan } from '../../agents/AgentAdapter.js';
|
|
2
|
+
import type { SetupCommandResult } from './SetupCommand.js';
|
|
3
|
+
export interface PiLoginLaunchPlanInput {
|
|
4
|
+
readonly adapterId: string;
|
|
5
|
+
readonly homeDirectory: string;
|
|
6
|
+
readonly launchPlan: AgentLaunchPlan;
|
|
7
|
+
readonly setupResult?: SetupCommandResult;
|
|
8
|
+
readonly writeLine?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const preparePiLoginLaunchPlan: (input: PiLoginLaunchPlanInput) => AgentLaunchPlan;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Adds first-run Pi login startup behavior without handling credentials in Outfitter.
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
const manualLoginMessage = 'Pi does not appear to be logged in yet. After Pi starts, run `/login` and choose a subscription such as Codex or provide an API key from another model provider.';
|
|
5
|
+
const automaticLoginMessage = 'Pi does not appear to be logged in yet. Outfitter will open `/login` automatically after Pi starts.';
|
|
6
|
+
const nonInteractivePiLaunchFlags = new Set(['--print', '-p', '--mode', '--export', '--list-models']);
|
|
7
|
+
export const preparePiLoginLaunchPlan = (input) => {
|
|
8
|
+
if (input.adapterId !== 'pi' || hasConfiguredPiLoginState(input.homeDirectory)) {
|
|
9
|
+
return input.launchPlan;
|
|
10
|
+
}
|
|
11
|
+
if (shouldAutoOpenPiLogin(input.setupResult, input.launchPlan.args)) {
|
|
12
|
+
writePiLoginMessage(input.writeLine, automaticLoginMessage);
|
|
13
|
+
return addPiLoginPrefillExtension(input.launchPlan);
|
|
14
|
+
}
|
|
15
|
+
writePiLoginMessage(input.writeLine, manualLoginMessage);
|
|
16
|
+
return input.launchPlan;
|
|
17
|
+
};
|
|
18
|
+
const addPiLoginPrefillExtension = (launchPlan) => {
|
|
19
|
+
const extensionPath = join(launchPlan.env.PI_CODING_AGENT_DIR, 'outfitter', 'prefill-login-extension.js');
|
|
20
|
+
mkdirSync(dirname(extensionPath), { recursive: true });
|
|
21
|
+
writeFileSync(extensionPath, piLoginPrefillExtensionContent);
|
|
22
|
+
return { ...launchPlan, args: ['--extension', extensionPath, ...launchPlan.args] };
|
|
23
|
+
};
|
|
24
|
+
const piLoginPrefillExtensionContent = `export default function outfitterLoginPrefill(pi) {
|
|
25
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
26
|
+
ctx.ui.setEditorText("/login");
|
|
27
|
+
ctx.ui.notify("Outfitter is opening /login so you can choose a provider.", "info");
|
|
28
|
+
await ctx.ui.custom((tui, _theme, _keybindings, done) => {
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
tui.focusedComponent?.handleInput?.("\\r");
|
|
31
|
+
done();
|
|
32
|
+
}, 25);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
render: () => [],
|
|
36
|
+
invalidate: () => undefined,
|
|
37
|
+
};
|
|
38
|
+
}, { overlay: true, overlayOptions: { nonCapturing: true, visible: () => false } });
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
const writePiLoginMessage = (writeLine, message) => {
|
|
43
|
+
/* v8 ignore next -- console fallback is direct CLI behavior; tests inject a writer for login messages. */
|
|
44
|
+
(writeLine ?? console.log)(message);
|
|
45
|
+
};
|
|
46
|
+
const shouldAutoOpenPiLogin = (setupResult, args) => setupResult?.welcomeResult !== undefined && !isNonInteractivePiLaunch(args);
|
|
47
|
+
const isNonInteractivePiLaunch = (args) => args.some((arg) => nonInteractivePiLaunchFlags.has(arg));
|
|
48
|
+
const hasConfiguredPiLoginState = (homeDirectory) => hasConfiguredPiStateFile(homeDirectory, 'auth.json') || hasConfiguredPiStateFile(homeDirectory, 'models.json');
|
|
49
|
+
const hasConfiguredPiStateFile = (homeDirectory, fileName) => {
|
|
50
|
+
const statePath = join(homeDirectory, '.pi', 'agent', fileName);
|
|
51
|
+
if (!existsSync(statePath)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return hasConfiguredPiStateEntries(JSON.parse(readFileSync(statePath, 'utf8')));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const hasConfiguredPiStateEntries = (value) => {
|
|
62
|
+
if (Array.isArray(value)) {
|
|
63
|
+
return value.length > 0;
|
|
64
|
+
}
|
|
65
|
+
if (value === null || typeof value !== 'object') {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const record = value;
|
|
69
|
+
const containerKeys = ['models', 'providers', 'model_providers'];
|
|
70
|
+
const presentContainers = containerKeys.filter((key) => Object.hasOwn(record, key));
|
|
71
|
+
if (presentContainers.length > 0) {
|
|
72
|
+
return presentContainers.some((key) => hasConfiguredPiStateEntries(record[key]));
|
|
73
|
+
}
|
|
74
|
+
return Object.keys(record).length > 0;
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=PiLoginLaunch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PiLoginLaunch.js","sourceRoot":"","sources":["../../../src/cli/commands/PiLoginLaunch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AgentAdapter, AgentLaunchPlan } from '../../agents/AgentAdapter.js';
|
|
2
|
+
import type { CommandObject } from './CommandObject.js';
|
|
3
|
+
import type { SetupCommandDependencies } from './SetupCommand.js';
|
|
4
|
+
export interface RunCommandInput {
|
|
5
|
+
readonly homeDirectory: string;
|
|
6
|
+
readonly projectDirectory: string;
|
|
7
|
+
readonly profileId?: string;
|
|
8
|
+
readonly agentId?: string;
|
|
9
|
+
readonly strict?: boolean;
|
|
10
|
+
readonly passThroughArgs?: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export interface RunCommandResult {
|
|
13
|
+
readonly profileId: string;
|
|
14
|
+
readonly agentId: string;
|
|
15
|
+
readonly launchPlan: AgentLaunchPlan;
|
|
16
|
+
readonly compositeProfileDirectory: string;
|
|
17
|
+
readonly warnings: readonly string[];
|
|
18
|
+
readonly exitCode: number;
|
|
19
|
+
}
|
|
20
|
+
export interface AgentProcessLauncher {
|
|
21
|
+
launch(plan: AgentLaunchPlan): Promise<number>;
|
|
22
|
+
}
|
|
23
|
+
export interface RunCommandDependencies extends SetupCommandDependencies {
|
|
24
|
+
readonly adapter?: AgentAdapter;
|
|
25
|
+
readonly launcher?: AgentProcessLauncher;
|
|
26
|
+
readonly writeError?: (message: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export declare const executeRunCommand: (input: RunCommandInput, dependencies?: RunCommandDependencies) => Promise<RunCommandResult>;
|
|
29
|
+
export declare const createRunCommand: (dependencies?: RunCommandDependencies) => CommandObject;
|
|
30
|
+
export declare const resolveChildExitCode: (code: number | null, signal: NodeJS.Signals | null) => number;
|